]> 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 0af1e9248d0f867e949c29f2a1e2ab4fc69ab65b..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;
@@ -171,17 +173,48 @@ static void prepare_backup_gpt_header(gpt_header *gpt_h)
        gpt_h->header_crc32 = cpu_to_le32(calc_crc32);
 }
 
-#ifdef CONFIG_EFI_PARTITION
+#if CONFIG_IS_ENABLED(EFI_PARTITION)
 /*
  * 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 */
@@ -279,7 +312,7 @@ int part_get_info_efi(struct blk_desc *dev_desc, int part,
                        print_efiname(&gpt_pte[part - 1]));
        strcpy((char *)info->type, "U-Boot");
        info->bootable = is_bootable(&gpt_pte[part - 1]);
-#ifdef CONFIG_PARTITION_UUIDS
+#if CONFIG_IS_ENABLED(PARTITION_UUIDS)
        uuid_bin_to_str(gpt_pte[part - 1].unique_partition_guid.b, info->uuid,
                        UUID_STR_FORMAT_GUID);
 #endif
@@ -296,25 +329,6 @@ int part_get_info_efi(struct blk_desc *dev_desc, int part,
        return 0;
 }
 
-int part_get_info_efi_by_name(struct blk_desc *dev_desc,
-       const char *name, disk_partition_t *info)
-{
-       int ret;
-       int i;
-       for (i = 1; i < GPT_ENTRY_NUMBERS; i++) {
-               ret = part_get_info_efi(dev_desc, i, info);
-               if (ret != 0) {
-                       /* no more entries in table */
-                       return -1;
-               }
-               if (strcmp(name, (const char *)info->name) == 0) {
-                       /* matched */
-                       return 0;
-               }
-       }
-       return -2;
-}
-
 static int part_test_efi(struct blk_desc *dev_desc)
 {
        ALLOC_CACHE_ALIGN_BUFFER_PAD(legacy_mbr, legacymbr, 1, dev_desc->blksz);
@@ -343,6 +357,13 @@ static int set_protective_mbr(struct blk_desc *dev_desc)
                printf("%s: calloc failed!\n", __func__);
                return -1;
        }
+
+       /* Read MBR to backup boot code if it exists */
+       if (blk_dread(dev_desc, 0, 1, p_mbr) != 1) {
+               error("** Can't read from device %d **\n", dev_desc->devnum);
+               return -1;
+       }
+
        /* Append signature */
        p_mbr->signature = MSDOS_MBR_SIGNATURE;
        p_mbr->partition_record[0].sys_ind = EFI_PMBR_OSTYPE_EFI_GPT;
@@ -385,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);
@@ -416,7 +437,7 @@ int gpt_fill_pte(gpt_header *gpt_h, gpt_entry *gpt_e,
                        le64_to_cpu(gpt_h->last_usable_lba);
        int i, k;
        size_t efiname_len, dosname_len;
-#ifdef CONFIG_PARTITION_UUIDS
+#if CONFIG_IS_ENABLED(PARTITION_UUIDS)
        char *str_uuid;
        unsigned char *bin_uuid;
 #endif
@@ -471,11 +492,11 @@ int gpt_fill_pte(gpt_header *gpt_h, gpt_entry *gpt_e,
                        &PARTITION_BASIC_DATA_GUID, 16);
 #endif
 
-#ifdef CONFIG_PARTITION_UUIDS
+#if CONFIG_IS_ENABLED(PARTITION_UUIDS)
                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;
@@ -510,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)
 {
@@ -518,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;
@@ -655,6 +721,10 @@ int gpt_verify_partitions(struct blk_desc *dev_desc,
                      (unsigned long long)partitions[i].size);
 
                if (le64_to_cpu(gpt_part_size) != partitions[i].size) {
+                       /* We do not check the extend partition size */
+                       if ((i == parts - 1) && (partitions[i].size == 0))
+                               continue;
+
                        error("Partition %s size: %llu does not match %llu!\n",
                              efi_str, (unsigned long long)gpt_part_size,
                              (unsigned long long)partitions[i].size);
@@ -886,9 +956,10 @@ static gpt_entry *alloc_read_gpt_entries(struct blk_desc *dev_desc,
        count = le32_to_cpu(pgpt_head->num_partition_entries) *
                le32_to_cpu(pgpt_head->sizeof_partition_entry);
 
-       debug("%s: count = %u * %u = %zu\n", __func__,
+       debug("%s: count = %u * %u = %lu\n", __func__,
              (u32) le32_to_cpu(pgpt_head->num_partition_entries),
-             (u32) le32_to_cpu(pgpt_head->sizeof_partition_entry), count);
+             (u32) le32_to_cpu(pgpt_head->sizeof_partition_entry),
+             (ulong)count);
 
        /* Allocate memory for PTE, remember to FREE */
        if (count != 0) {
@@ -897,9 +968,8 @@ static gpt_entry *alloc_read_gpt_entries(struct blk_desc *dev_desc,
        }
 
        if (count == 0 || pte == NULL) {
-               printf("%s: ERROR: Can't allocate 0x%zX "
-                      "bytes for GPT Entries\n",
-                       __func__, count);
+               printf("%s: ERROR: Can't allocate %#lX bytes for GPT Entries\n",
+                      __func__, (ulong)count);
                return NULL;
        }
 
@@ -954,6 +1024,7 @@ static int is_pte_valid(gpt_entry * pte)
 U_BOOT_PART_TYPE(a_efi) = {
        .name           = "EFI",
        .part_type      = PART_TYPE_EFI,
+       .max_entries    = GPT_ENTRY_NUMBERS,
        .get_info       = part_get_info_ptr(part_get_info_efi),
        .print          = part_print_ptr(part_print_efi),
        .test           = part_test_efi,