#include <ide.h>
#include <inttypes.h>
#include <malloc.h>
+#include <memalign.h>
#include <part_efi.h>
#include <linux/ctype.h>
val = le64_to_cpu(gpt_h->my_lba);
gpt_h->my_lba = gpt_h->alternate_lba;
gpt_h->alternate_lba = cpu_to_le64(val);
+ gpt_h->partition_entry_lba =
+ cpu_to_le64(le64_to_cpu(gpt_h->last_usable_lba) + 1);
gpt_h->header_crc32 = 0;
calc_crc32 = efi_crc32((const unsigned char *)gpt_h,
uuid_bin = (unsigned char *)gpt_pte[i].partition_type_guid.b;
uuid_bin_to_str(uuid_bin, uuid, UUID_STR_FORMAT_GUID);
printf("\ttype:\t%s\n", uuid);
+#ifdef CONFIG_PARTITION_TYPE_GUID
+ if (!uuid_guid_get_str(uuid_bin, uuid))
+ printf("\ttype:\t%s\n", uuid);
+#endif
uuid_bin = (unsigned char *)gpt_pte[i].unique_partition_guid.b;
uuid_bin_to_str(uuid_bin, uuid, UUID_STR_FORMAT_GUID);
printf("\tguid:\t%s\n", uuid);
uuid_bin_to_str(gpt_pte[part - 1].unique_partition_guid.b, info->uuid,
UUID_STR_FORMAT_GUID);
#endif
+#ifdef CONFIG_PARTITION_TYPE_GUID
+ uuid_bin_to_str(gpt_pte[part - 1].partition_type_guid.b,
+ info->type_guid, UUID_STR_FORMAT_GUID);
+#endif
debug("%s: start 0x" LBAF ", size 0x" LBAF ", name %s\n", __func__,
info->start, info->size, info->name);
p_mbr->signature = MSDOS_MBR_SIGNATURE;
p_mbr->partition_record[0].sys_ind = EFI_PMBR_OSTYPE_EFI_GPT;
p_mbr->partition_record[0].start_sect = 1;
- p_mbr->partition_record[0].nr_sects = (u32) dev_desc->lba;
+ p_mbr->partition_record[0].nr_sects = (u32) dev_desc->lba - 1;
/* Write MBR sector to the MMC device */
if (dev_desc->block_write(dev_desc->dev, 0, 1, p_mbr) != 1) {
char *str_uuid;
unsigned char *bin_uuid;
#endif
+#ifdef CONFIG_PARTITION_TYPE_GUID
+ char *str_type_guid;
+ unsigned char *bin_type_guid;
+#endif
for (i = 0; i < parts; i++) {
/* partition starting lba */
else
gpt_e[i].ending_lba = cpu_to_le64(offset - 1);
+#ifdef CONFIG_PARTITION_TYPE_GUID
+ str_type_guid = partitions[i].type_guid;
+ bin_type_guid = gpt_e[i].partition_type_guid.b;
+ if (strlen(str_type_guid)) {
+ if (uuid_str_to_bin(str_type_guid, bin_type_guid,
+ UUID_STR_FORMAT_GUID)) {
+ printf("Partition no. %d: invalid type guid: %s\n",
+ i, str_type_guid);
+ return -1;
+ }
+ } else {
+ /* default partition type GUID */
+ memcpy(bin_type_guid,
+ &PARTITION_BASIC_DATA_GUID, 16);
+ }
+#else
/* partition type GUID */
memcpy(gpt_e[i].partition_type_guid.b,
&PARTITION_BASIC_DATA_GUID, 16);
+#endif
#ifdef CONFIG_PARTITION_UUIDS
str_uuid = partitions[i].uuid;
memset(&gpt_e[i].attributes, 0,
sizeof(gpt_entry_attributes));
+ if (partitions[i].bootable)
+ gpt_e[i].attributes.fields.legacy_bios_bootable = 1;
+
/* partition name */
efiname_len = sizeof(gpt_e[i].partition_name)
/ sizeof(efi_char16_t);
free(gpt_h);
return ret;
}
+
+static void gpt_convert_efi_name_to_char(char *s, efi_char16_t *es, int n)
+{
+ char *ess = (char *)es;
+ int i, j;
+
+ memset(s, '\0', n);
+
+ for (i = 0, j = 0; j < n; i += 2, j++) {
+ s[j] = ess[i];
+ if (!ess[i])
+ return;
+ }
+}
+
+int gpt_verify_headers(block_dev_desc_t *dev_desc, gpt_header *gpt_head,
+ gpt_entry **gpt_pte)
+{
+ /*
+ * 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__);
+ return -1;
+ }
+ if (is_gpt_valid(dev_desc, (dev_desc->lba - 1),
+ gpt_head, gpt_pte) != 1) {
+ printf("%s: *** ERROR: Invalid Backup GPT ***\n",
+ __func__);
+ return -1;
+ }
+
+ return 0;
+}
+
+int gpt_verify_partitions(block_dev_desc_t *dev_desc,
+ disk_partition_t *partitions, int parts,
+ gpt_header *gpt_head, gpt_entry **gpt_pte)
+{
+ char efi_str[PARTNAME_SZ + 1];
+ u64 gpt_part_size;
+ gpt_entry *gpt_e;
+ int ret, i;
+
+ ret = gpt_verify_headers(dev_desc, gpt_head, gpt_pte);
+ if (ret)
+ return ret;
+
+ gpt_e = *gpt_pte;
+
+ for (i = 0; i < parts; i++) {
+ if (i == gpt_head->num_partition_entries) {
+ error("More partitions than allowed!\n");
+ return -1;
+ }
+
+ /* Check if GPT and ENV partition names match */
+ gpt_convert_efi_name_to_char(efi_str, gpt_e[i].partition_name,
+ PARTNAME_SZ + 1);
+
+ debug("%s: part: %2d name - GPT: %16s, ENV: %16s ",
+ __func__, i, efi_str, partitions[i].name);
+
+ if (strncmp(efi_str, (char *)partitions[i].name,
+ sizeof(partitions->name))) {
+ error("Partition name: %s does not match %s!\n",
+ efi_str, (char *)partitions[i].name);
+ return -1;
+ }
+
+ /* Check if GPT and ENV sizes match */
+ gpt_part_size = le64_to_cpu(gpt_e[i].ending_lba) -
+ le64_to_cpu(gpt_e[i].starting_lba) + 1;
+ debug("size(LBA) - GPT: %8llu, ENV: %8llu ",
+ gpt_part_size, (u64) partitions[i].size);
+
+ if (le64_to_cpu(gpt_part_size) != partitions[i].size) {
+ error("Partition %s size: %llu does not match %llu!\n",
+ efi_str, gpt_part_size, (u64) partitions[i].size);
+ return -1;
+ }
+
+ /*
+ * Start address is optional - check only if provided
+ * in '$partition' variable
+ */
+ if (!partitions[i].start) {
+ debug("\n");
+ continue;
+ }
+
+ /* Check if GPT and ENV start LBAs match */
+ debug("start LBA - GPT: %8llu, ENV: %8llu\n",
+ le64_to_cpu(gpt_e[i].starting_lba),
+ (u64) partitions[i].start);
+
+ if (le64_to_cpu(gpt_e[i].starting_lba) != partitions[i].start) {
+ error("Partition %s start: %llu does not match %llu!\n",
+ efi_str, le64_to_cpu(gpt_e[i].starting_lba),
+ (u64) partitions[i].start);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+int is_valid_gpt_buf(block_dev_desc_t *dev_desc, void *buf)
+{
+ gpt_header *gpt_h;
+ gpt_entry *gpt_e;
+
+ /* determine start of GPT Header in the buffer */
+ gpt_h = buf + (GPT_PRIMARY_PARTITION_TABLE_LBA *
+ dev_desc->blksz);
+ if (validate_gpt_header(gpt_h, GPT_PRIMARY_PARTITION_TABLE_LBA,
+ dev_desc->lba))
+ return -1;
+
+ /* determine start of GPT Entries in the buffer */
+ gpt_e = buf + (le64_to_cpu(gpt_h->partition_entry_lba) *
+ dev_desc->blksz);
+ if (validate_gpt_entries(gpt_h, gpt_e))
+ return -1;
+
+ return 0;
+}
+
+int write_mbr_and_gpt_partitions(block_dev_desc_t *dev_desc, void *buf)
+{
+ gpt_header *gpt_h;
+ gpt_entry *gpt_e;
+ int gpt_e_blk_cnt;
+ lbaint_t lba;
+ int cnt;
+
+ if (is_valid_gpt_buf(dev_desc, buf))
+ return -1;
+
+ /* determine start of GPT Header in the buffer */
+ gpt_h = buf + (GPT_PRIMARY_PARTITION_TABLE_LBA *
+ dev_desc->blksz);
+
+ /* determine start of GPT Entries in the buffer */
+ gpt_e = buf + (le64_to_cpu(gpt_h->partition_entry_lba) *
+ dev_desc->blksz);
+ gpt_e_blk_cnt = BLOCK_CNT((le32_to_cpu(gpt_h->num_partition_entries) *
+ le32_to_cpu(gpt_h->sizeof_partition_entry)),
+ dev_desc);
+
+ /* write MBR */
+ lba = 0; /* MBR is always at 0 */
+ cnt = 1; /* MBR (1 block) */
+ if (dev_desc->block_write(dev_desc->dev, lba, cnt, buf) != cnt) {
+ printf("%s: failed writing '%s' (%d blks at 0x" LBAF ")\n",
+ __func__, "MBR", cnt, lba);
+ return 1;
+ }
+
+ /* write Primary GPT */
+ lba = GPT_PRIMARY_PARTITION_TABLE_LBA;
+ cnt = 1; /* GPT Header (1 block) */
+ if (dev_desc->block_write(dev_desc->dev, lba, cnt, gpt_h) != cnt) {
+ printf("%s: failed writing '%s' (%d blks at 0x" LBAF ")\n",
+ __func__, "Primary GPT Header", cnt, lba);
+ return 1;
+ }
+
+ lba = le64_to_cpu(gpt_h->partition_entry_lba);
+ cnt = gpt_e_blk_cnt;
+ if (dev_desc->block_write(dev_desc->dev, lba, cnt, gpt_e) != cnt) {
+ printf("%s: failed writing '%s' (%d blks at 0x" LBAF ")\n",
+ __func__, "Primary GPT Entries", cnt, lba);
+ return 1;
+ }
+
+ prepare_backup_gpt_header(gpt_h);
+
+ /* write Backup GPT */
+ lba = le64_to_cpu(gpt_h->partition_entry_lba);
+ cnt = gpt_e_blk_cnt;
+ if (dev_desc->block_write(dev_desc->dev, lba, cnt, gpt_e) != cnt) {
+ printf("%s: failed writing '%s' (%d blks at 0x" LBAF ")\n",
+ __func__, "Backup GPT Entries", cnt, lba);
+ return 1;
+ }
+
+ lba = le64_to_cpu(gpt_h->my_lba);
+ cnt = 1; /* GPT Header (1 block) */
+ if (dev_desc->block_write(dev_desc->dev, lba, cnt, gpt_h) != cnt) {
+ printf("%s: failed writing '%s' (%d blks at 0x" LBAF ")\n",
+ __func__, "Backup GPT Header", cnt, lba);
+ return 1;
+ }
+
+ return 0;
+}
#endif
/*