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