Julian Hall | 69a25f3 | 2022-09-26 14:55:57 +0100 | [diff] [blame^] | 1 | /* |
| 2 | * Copyright (c) 2022, Arm Limited and Contributors. All rights reserved. |
| 3 | * |
| 4 | * SPDX-License-Identifier: BSD-3-Clause |
| 5 | */ |
| 6 | |
| 7 | |
| 8 | #include <string> |
| 9 | #include <cstring> |
| 10 | #include <common/uuid/uuid.h> |
| 11 | #include <service/block_storage/block_store/device/ram/ram_block_store.h> |
| 12 | #include <service/block_storage/config/ref/ref_partition_configurator.h> |
| 13 | #include <media/volume/index/volume_index.h> |
| 14 | #include <media/volume/block_io_dev/block_io_dev.h> |
| 15 | #include <media/volume/base_io_dev/base_io_dev.h> |
| 16 | #include <media/disk/disk_images/ref_partition.h> |
| 17 | #include <media/disk/partition_table.h> |
| 18 | #include <CppUTest/TestHarness.h> |
| 19 | |
| 20 | TEST_GROUP(PartitionTableTests) |
| 21 | { |
| 22 | void setup() |
| 23 | { |
| 24 | /* Load reference GPT image into ram block store */ |
| 25 | size_t block_size = PLAT_PARTITION_BLOCK_SIZE; |
| 26 | size_t num_blocks = ref_partition_data_length / block_size; |
| 27 | |
| 28 | m_block_store = ram_block_store_init(&m_ram_block_store, |
| 29 | NULL, |
| 30 | num_blocks, block_size, ref_partition_data); |
| 31 | |
| 32 | CHECK_TRUE(m_block_store); |
| 33 | |
| 34 | memset(m_partition_guid.octets, 0, sizeof(m_partition_guid.octets)); |
| 35 | |
| 36 | m_dev_handle = 0; |
| 37 | m_volume_spec = 0; |
| 38 | |
| 39 | int result = block_io_dev_init(&m_block_io_dev, |
| 40 | m_block_store, &m_partition_guid, |
| 41 | &m_dev_handle, &m_volume_spec); |
| 42 | |
| 43 | LONGS_EQUAL(0, result); |
| 44 | CHECK_TRUE(m_dev_handle); |
| 45 | CHECK_TRUE(m_volume_spec); |
| 46 | |
| 47 | volume_index_init(); |
| 48 | volume_index_add(TEST_VOLUME_ID, m_dev_handle, m_volume_spec); |
| 49 | } |
| 50 | |
| 51 | void teardown() |
| 52 | { |
| 53 | block_io_dev_deinit(&m_block_io_dev); |
| 54 | ram_block_store_deinit(&m_ram_block_store); |
| 55 | volume_index_clear(); |
| 56 | } |
| 57 | |
| 58 | void uuid_from_canonical(uuid_t *uuid, const char *canonical) |
| 59 | { |
| 60 | uuid_parse_to_octets_reversed(canonical, (uint8_t*)uuid, sizeof(uuid_t)); |
| 61 | } |
| 62 | |
| 63 | void corrupt_mbr() |
| 64 | { |
| 65 | /* Scribble over the protective MBR signature */ |
| 66 | static const char scribble[] = "scribble"; |
| 67 | psa_status_t status = ram_block_store_modify( |
| 68 | &m_ram_block_store, 510, |
| 69 | (const uint8_t*)scribble, sizeof(scribble)); |
| 70 | LONGS_EQUAL(PSA_SUCCESS, status); |
| 71 | } |
| 72 | |
| 73 | void corrupt_primary_gpt_header() |
| 74 | { |
| 75 | /* Scribble over the primary GPT header in block 1 */ |
| 76 | static const char scribble[] = "scribble"; |
| 77 | psa_status_t status = ram_block_store_modify( |
| 78 | &m_ram_block_store, PLAT_PARTITION_BLOCK_SIZE * 1, |
| 79 | (const uint8_t*)scribble, sizeof(scribble)); |
| 80 | LONGS_EQUAL(PSA_SUCCESS, status); |
| 81 | } |
| 82 | |
| 83 | static const unsigned int TEST_VOLUME_ID = 5; |
| 84 | static const uint32_t CLIENT_ID = 0; |
| 85 | static const size_t FIRST_USABLE_LBA = 34; |
| 86 | |
| 87 | struct uuid_octets m_partition_guid; |
| 88 | struct block_store *m_block_store; |
| 89 | struct ram_block_store m_ram_block_store; |
| 90 | struct block_io_dev m_block_io_dev; |
| 91 | uintptr_t m_dev_handle; |
| 92 | uintptr_t m_volume_spec; |
| 93 | }; |
| 94 | |
| 95 | TEST(PartitionTableTests, loadRefPartitionTable) |
| 96 | { |
| 97 | int result = load_partition_table(TEST_VOLUME_ID); |
| 98 | LONGS_EQUAL(0, result); |
| 99 | |
| 100 | /* Check for expected partition entries */ |
| 101 | const partition_entry_t *partition_entry = NULL; |
| 102 | uuid_t partition_guid; |
| 103 | |
| 104 | uuid_from_canonical(&partition_guid, REF_PARTITION_1_GUID); |
| 105 | partition_entry = get_partition_entry_by_uuid(&partition_guid); |
| 106 | CHECK_TRUE(partition_entry); |
| 107 | UNSIGNED_LONGS_EQUAL( |
| 108 | FIRST_USABLE_LBA + REF_PARTITION_1_STARTING_LBA, |
| 109 | partition_entry->start / PLAT_PARTITION_BLOCK_SIZE); |
| 110 | UNSIGNED_LONGS_EQUAL( |
| 111 | (REF_PARTITION_1_ENDING_LBA - REF_PARTITION_1_STARTING_LBA + 1), |
| 112 | partition_entry->length / PLAT_PARTITION_BLOCK_SIZE); |
| 113 | |
| 114 | uuid_from_canonical(&partition_guid, REF_PARTITION_2_GUID); |
| 115 | partition_entry = get_partition_entry_by_uuid(&partition_guid); |
| 116 | CHECK_TRUE(partition_entry); |
| 117 | UNSIGNED_LONGS_EQUAL( |
| 118 | FIRST_USABLE_LBA + REF_PARTITION_2_STARTING_LBA, |
| 119 | partition_entry->start / PLAT_PARTITION_BLOCK_SIZE); |
| 120 | UNSIGNED_LONGS_EQUAL( |
| 121 | (REF_PARTITION_2_ENDING_LBA - REF_PARTITION_2_STARTING_LBA + 1), |
| 122 | partition_entry->length / PLAT_PARTITION_BLOCK_SIZE); |
| 123 | |
| 124 | uuid_from_canonical(&partition_guid, REF_PARTITION_3_GUID); |
| 125 | partition_entry = get_partition_entry_by_uuid(&partition_guid); |
| 126 | CHECK_TRUE(partition_entry); |
| 127 | UNSIGNED_LONGS_EQUAL( |
| 128 | FIRST_USABLE_LBA + REF_PARTITION_3_STARTING_LBA, |
| 129 | partition_entry->start / PLAT_PARTITION_BLOCK_SIZE); |
| 130 | UNSIGNED_LONGS_EQUAL( |
| 131 | (REF_PARTITION_3_ENDING_LBA - REF_PARTITION_3_STARTING_LBA + 1), |
| 132 | partition_entry->length / PLAT_PARTITION_BLOCK_SIZE); |
| 133 | |
| 134 | uuid_from_canonical(&partition_guid, REF_PARTITION_4_GUID); |
| 135 | partition_entry = get_partition_entry_by_uuid(&partition_guid); |
| 136 | CHECK_TRUE(partition_entry); |
| 137 | UNSIGNED_LONGS_EQUAL( |
| 138 | FIRST_USABLE_LBA + REF_PARTITION_4_STARTING_LBA, |
| 139 | partition_entry->start / PLAT_PARTITION_BLOCK_SIZE); |
| 140 | UNSIGNED_LONGS_EQUAL( |
| 141 | (REF_PARTITION_4_ENDING_LBA - REF_PARTITION_4_STARTING_LBA + 1), |
| 142 | partition_entry->length / PLAT_PARTITION_BLOCK_SIZE); |
| 143 | } |
| 144 | |
| 145 | TEST(PartitionTableTests, detectCorruptedMbr) |
| 146 | { |
| 147 | corrupt_mbr(); |
| 148 | int result = load_partition_table(TEST_VOLUME_ID); |
| 149 | LONGS_EQUAL(-ENOENT, result); |
| 150 | } |
| 151 | |
| 152 | // Shows up defect in TF-A where failed GPT header CRC results in an assert. |
| 153 | IGNORE_TEST(PartitionTableTests, detectCorruptedGptHeader) |
| 154 | { |
| 155 | /* Load should be successful with a corrupted primary GPT header as |
| 156 | * backup is still available. |
| 157 | */ |
| 158 | corrupt_primary_gpt_header(); |
| 159 | int result = load_partition_table(TEST_VOLUME_ID); |
| 160 | LONGS_EQUAL(0, result); |
| 161 | } |