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