]> git.sur5r.net Git - u-boot/blobdiff - disk/part_efi.c
Merge branch 'rmobile' of git://git.denx.de/u-boot-sh
[u-boot] / disk / part_efi.c
index 893cbbdbdaeb5cdbac23b1e24ef0bec7819a33bb..71c3cb3f78d9fbffae660c019cfa54d3bb4ef7e1 100644 (file)
 #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/compiler.h>
 #include <linux/ctype.h>
 
 DECLARE_GLOBAL_DATA_PTR;
@@ -176,12 +178,43 @@ static void prepare_backup_gpt_header(gpt_header *gpt_h)
  * Public Functions (include/part.h)
  */
 
+/*
+ * UUID is displayed as 32 hexadecimal digits, in 5 groups,
+ * separated by hyphens, in the form 8-4-4-4-12 for a total of 36 characters
+ */
+int get_disk_guid(struct blk_desc * dev_desc, char *guid)
+{
+       ALLOC_CACHE_ALIGN_BUFFER_PAD(gpt_header, gpt_head, 1, dev_desc->blksz);
+       gpt_entry *gpt_pte = NULL;
+       unsigned char *guid_bin;
+
+       /* This function validates AND fills in the GPT header and PTE */
+       if (is_gpt_valid(dev_desc, GPT_PRIMARY_PARTITION_TABLE_LBA,
+                        gpt_head, &gpt_pte) != 1) {
+               printf("%s: *** ERROR: Invalid GPT ***\n", __func__);
+               if (is_gpt_valid(dev_desc, dev_desc->lba - 1,
+                                gpt_head, &gpt_pte) != 1) {
+                       printf("%s: *** ERROR: Invalid Backup GPT ***\n",
+                              __func__);
+                       return -EINVAL;
+               } else {
+                       printf("%s: ***        Using Backup GPT ***\n",
+                              __func__);
+               }
+       }
+
+       guid_bin = gpt_head->disk_guid.b;
+       uuid_bin_to_str(guid_bin, guid, UUID_STR_FORMAT_GUID);
+
+       return 0;
+}
+
 void part_print_efi(struct blk_desc *dev_desc)
 {
        ALLOC_CACHE_ALIGN_BUFFER_PAD(gpt_header, gpt_head, 1, dev_desc->blksz);
        gpt_entry *gpt_pte = NULL;
        int i = 0;
-       char uuid[37];
+       char uuid[UUID_STR_LEN + 1];
        unsigned char *uuid_bin;
 
        /* This function validates AND fills in the GPT header and PTE */
@@ -373,8 +406,8 @@ int write_gpt_table(struct blk_desc *dev_desc,
        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);
@@ -463,7 +496,7 @@ int gpt_fill_pte(gpt_header *gpt_h, gpt_entry *gpt_e,
                str_uuid = partitions[i].uuid;
                bin_uuid = gpt_e[i].unique_partition_guid.b;
 
-               if (uuid_str_to_bin(str_uuid, bin_uuid, UUID_STR_FORMAT_STD)) {
+               if (uuid_str_to_bin(str_uuid, bin_uuid, UUID_STR_FORMAT_GUID)) {
                        printf("Partition no. %d: invalid guid: %s\n",
                                i, str_uuid);
                        return -1;
@@ -498,6 +531,49 @@ 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 = 2;
+       int __maybe_unused 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);
+#endif
+
+#if defined(CONFIG_OF_CONTROL)
+       /*
+        * 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);
+
+       /*
+        * The earliest LBA this can be at is LBA#2 (i.e. right behind
+        * the (protective) MBR and the GPT header.
+        */
+       if (offset_blks < 2)
+               offset_blks = 2;
+
+       return offset_blks;
+}
+
 int gpt_fill_header(struct blk_desc *dev_desc, gpt_header *gpt_h,
                char *str_guid, int parts_count)
 {
@@ -506,9 +582,11 @@ int gpt_fill_header(struct blk_desc *dev_desc, gpt_header *gpt_h,
        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;