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_volume/block_volume.h>
15 #include <media/disk/disk_images/ref_partition.h>
16 #include <media/disk/formatter/disk_formatter.h>
17 #include <media/disk/partition_table.h>
18 #include <CppUTest/TestHarness.h>
19
TEST_GROUP(PartitionTableTests)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);
31
32 CHECK_TRUE(m_block_store);
33
34 memset(m_partition_guid.octets, 0, sizeof(m_partition_guid.octets));
35
36 m_volume = NULL;
37
38 int result = block_volume_init(&m_block_volume,
39 m_block_store, &m_partition_guid,
40 &m_volume);
41
42 LONGS_EQUAL(0, result);
43 CHECK_TRUE(m_volume);
44
45 result = disk_formatter_clone(
46 m_volume->dev_handle, m_volume->io_spec,
47 ref_partition_data, ref_partition_data_length);
48
49 LONGS_EQUAL(0, result);
50
51 volume_index_init();
52 volume_index_add(VOLUME_ID_SECURE_FLASH, m_volume);
53 }
54
55 void teardown()
56 {
57 block_volume_deinit(&m_block_volume);
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 {
64 uuid_parse_to_guid_octets(canonical, (uint8_t*)uuid, sizeof(uuid_t));
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
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;
93 struct block_volume m_block_volume;
94 struct volume *m_volume;
95 };
96
TEST(PartitionTableTests,loadRefPartitionTable)97 TEST(PartitionTableTests, loadRefPartitionTable)
98 {
99 int result = load_partition_table(VOLUME_ID_SECURE_FLASH);
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
TEST(PartitionTableTests,detectCorruptedMbr)147 TEST(PartitionTableTests, detectCorruptedMbr)
148 {
149 corrupt_mbr();
150 int result = load_partition_table(VOLUME_ID_SECURE_FLASH);
151 LONGS_EQUAL(-ENOENT, result);
152 }
153
154 // Shows up defect in TF-A where failed GPT header CRC results in an assert.
IGNORE_TEST(PartitionTableTests,detectCorruptedGptHeader)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();
161 int result = load_partition_table(VOLUME_ID_SECURE_FLASH);
162 LONGS_EQUAL(0, result);
163 }
164