+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2008 RuggedCom, Inc.
* Richard Retanubun <RichardRetanubun@RuggedCom.com>
- *
- * SPDX-License-Identifier: GPL-2.0+
*/
/*
DECLARE_GLOBAL_DATA_PTR;
-#ifdef HAVE_BLOCK_DEVICE
+#ifdef CONFIG_HAVE_BLOCK_DEVICE
/**
* efi_crc32() - EFI version of crc32 function
* @buf: buffer to calculate crc32 of
static int set_protective_mbr(struct blk_desc *dev_desc)
{
/* Setup the Protective MBR */
- ALLOC_CACHE_ALIGN_BUFFER(legacy_mbr, p_mbr, 1);
+ ALLOC_CACHE_ALIGN_BUFFER_PAD(legacy_mbr, p_mbr, 1, dev_desc->blksz);
memset(p_mbr, 0, sizeof(*p_mbr));
if (p_mbr == NULL) {
/* 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);
+ pr_err("** Can't read from device %d **\n", dev_desc->devnum);
return -1;
}
return -1;
}
-int gpt_fill_pte(gpt_header *gpt_h, gpt_entry *gpt_e,
- disk_partition_t *partitions, int parts)
+int gpt_fill_pte(struct blk_desc *dev_desc,
+ gpt_header *gpt_h, gpt_entry *gpt_e,
+ disk_partition_t *partitions, int parts)
{
lbaint_t offset = (lbaint_t)le64_to_cpu(gpt_h->first_usable_lba);
lbaint_t last_usable_lba = (lbaint_t)
char *str_type_guid;
unsigned char *bin_type_guid;
#endif
+ size_t hdr_start = gpt_h->my_lba;
+ size_t hdr_end = hdr_start + 1;
+
+ size_t pte_start = gpt_h->partition_entry_lba;
+ size_t pte_end = pte_start +
+ gpt_h->num_partition_entries * gpt_h->sizeof_partition_entry /
+ dev_desc->blksz;
for (i = 0; i < parts; i++) {
/* partition starting lba */
lbaint_t start = partitions[i].start;
lbaint_t size = partitions[i].size;
- if (start && (start < offset)) {
- printf("Partition overlap\n");
- return -1;
- }
-
if (start) {
- gpt_e[i].starting_lba = cpu_to_le64(start);
offset = start + size;
} else {
- gpt_e[i].starting_lba = cpu_to_le64(offset);
+ start = offset;
offset += size;
}
+
+ /*
+ * If our partition overlaps with either the GPT
+ * header, or the partition entry, reject it.
+ */
+ if (((start < hdr_end && hdr_start < (start + size)) ||
+ (start < pte_end && pte_start < (start + size)))) {
+ printf("Partition overlap\n");
+ return -1;
+ }
+
+ gpt_e[i].starting_lba = cpu_to_le64(start);
+
if (offset > (last_usable_lba + 1)) {
printf("Partitions layout exceds disk size\n");
return -1;
int gpt_restore(struct blk_desc *dev_desc, char *str_disk_guid,
disk_partition_t *partitions, int parts_count)
{
- int ret;
-
- gpt_header *gpt_h = calloc(1, PAD_TO_BLOCKSIZE(sizeof(gpt_header),
- dev_desc));
+ gpt_header *gpt_h;
gpt_entry *gpt_e;
+ int ret, size;
+ size = PAD_TO_BLOCKSIZE(sizeof(gpt_header), dev_desc);
+ gpt_h = malloc_cache_aligned(size);
if (gpt_h == NULL) {
printf("%s: calloc failed!\n", __func__);
return -1;
}
+ memset(gpt_h, 0, size);
- gpt_e = calloc(1, PAD_TO_BLOCKSIZE(GPT_ENTRY_NUMBERS
- * sizeof(gpt_entry),
- dev_desc));
+ size = PAD_TO_BLOCKSIZE(GPT_ENTRY_NUMBERS * sizeof(gpt_entry),
+ dev_desc);
+ gpt_e = malloc_cache_aligned(size);
if (gpt_e == NULL) {
printf("%s: calloc failed!\n", __func__);
free(gpt_h);
return -1;
}
+ memset(gpt_e, 0, size);
/* Generate Primary GPT header (LBA1) */
ret = gpt_fill_header(dev_desc, gpt_h, str_disk_guid, parts_count);
goto err;
/* Generate partition entries */
- ret = gpt_fill_pte(gpt_h, gpt_e, partitions, parts_count);
+ ret = gpt_fill_pte(dev_desc, gpt_h, gpt_e, partitions, parts_count);
if (ret)
goto err;
for (i = 0; i < parts; i++) {
if (i == gpt_head->num_partition_entries) {
- error("More partitions than allowed!\n");
+ pr_err("More partitions than allowed!\n");
return -1;
}
if (strncmp(efi_str, (char *)partitions[i].name,
sizeof(partitions->name))) {
- error("Partition name: %s does not match %s!\n",
+ pr_err("Partition name: %s does not match %s!\n",
efi_str, (char *)partitions[i].name);
return -1;
}
if ((i == parts - 1) && (partitions[i].size == 0))
continue;
- error("Partition %s size: %llu does not match %llu!\n",
+ pr_err("Partition %s size: %llu does not match %llu!\n",
efi_str, (unsigned long long)gpt_part_size,
(unsigned long long)partitions[i].size);
return -1;
(unsigned long long)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",
+ pr_err("Partition %s start: %llu does not match %llu!\n",
efi_str, le64_to_cpu(gpt_e[i].starting_lba),
(unsigned long long)partitions[i].start);
return -1;
static int is_gpt_valid(struct blk_desc *dev_desc, u64 lba,
gpt_header *pgpt_head, gpt_entry **pgpt_pte)
{
+ /* Confirm valid arguments prior to allocation. */
if (!dev_desc || !pgpt_head) {
printf("%s: Invalid Argument(s)\n", __func__);
return 0;
}
+ ALLOC_CACHE_ALIGN_BUFFER_PAD(legacy_mbr, mbr, 1, dev_desc->blksz);
+
+ /* Read MBR Header from device */
+ if (blk_dread(dev_desc, 0, 1, (ulong *)mbr) != 1) {
+ printf("*** ERROR: Can't read MBR header ***\n");
+ return 0;
+ }
+
/* Read GPT Header from device */
if (blk_dread(dev_desc, (lbaint_t)lba, 1, pgpt_head) != 1) {
printf("*** ERROR: Can't read GPT header ***\n");
if (validate_gpt_header(pgpt_head, (lbaint_t)lba, dev_desc->lba))
return 0;
+ if (dev_desc->sig_type == SIG_TYPE_NONE) {
+ efi_guid_t empty = {};
+ if (memcmp(&pgpt_head->disk_guid, &empty, sizeof(empty))) {
+ dev_desc->sig_type = SIG_TYPE_GUID;
+ memcpy(&dev_desc->guid_sig, &pgpt_head->disk_guid,
+ sizeof(empty));
+ } else if (mbr->unique_mbr_signature != 0) {
+ dev_desc->sig_type = SIG_TYPE_MBR;
+ dev_desc->mbr_sig = mbr->unique_mbr_signature;
+ }
+ }
+
/* Read and allocate Partition Table Entries */
*pgpt_pte = alloc_read_gpt_entries(dev_desc, pgpt_head);
if (*pgpt_pte == NULL) {