1 /*- 2 * BSD LICENSE 3 * 4 * Copyright (c) Intel Corporation. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * * Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * * Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * * Neither the name of the copyright holder nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #include "spdk_cunit.h" 35 36 #include "common/lib/test_env.c" 37 38 #include "bdev/gpt/gpt.c" 39 40 static void 41 test_check_mbr(void) 42 { 43 struct spdk_gpt *gpt; 44 struct spdk_mbr *mbr; 45 unsigned char a[SPDK_GPT_BUFFER_SIZE]; 46 int re; 47 48 /* Set gpt is NULL */ 49 re = spdk_gpt_parse_mbr(NULL); 50 CU_ASSERT(re == -1); 51 52 /* Set gpt->buf is NULL */ 53 gpt = calloc(1, sizeof(*gpt)); 54 SPDK_CU_ASSERT_FATAL(gpt != NULL); 55 re = spdk_gpt_parse_mbr(gpt); 56 CU_ASSERT(re == -1); 57 58 /* Set *gpt is "aaa...", all are mismatch include mbr_signature */ 59 memset(a, 'a', sizeof(a)); 60 gpt->buf = &a[0]; 61 re = spdk_gpt_check_mbr(gpt); 62 CU_ASSERT(re == -1); 63 64 /* Set mbr->mbr_signature matched, start lba mismatch */ 65 mbr = (struct spdk_mbr *)gpt->buf; 66 mbr->mbr_signature = 0xAA55; 67 re = spdk_gpt_check_mbr(gpt); 68 CU_ASSERT(re == -1); 69 70 /* Set mbr->partitions[0].start lba matched, os_type mismatch */ 71 mbr->partitions[0].start_lba = 1; 72 re = spdk_gpt_check_mbr(gpt); 73 CU_ASSERT(re == -1); 74 75 /* Set mbr->partitions[0].os_type matched, size_lba mismatch */ 76 mbr->partitions[0].os_type = 0xEE; 77 re = spdk_gpt_check_mbr(gpt); 78 CU_ASSERT(re == -1); 79 80 /* Set mbr->partitions[0].size_lba matched, passing case */ 81 mbr->partitions[0].size_lba = 0xFFFFFFFF; 82 re = spdk_gpt_check_mbr(gpt); 83 CU_ASSERT(re == 0); 84 85 free(gpt); 86 } 87 88 static void 89 test_read_header(void) 90 { 91 struct spdk_gpt *gpt; 92 struct spdk_gpt_header *head; 93 unsigned char a[SPDK_GPT_BUFFER_SIZE]; 94 int re; 95 96 /* spdk_gpt_read_header(NULL) does not exist, NULL is filtered out in spdk_gpt_parse_mbr() */ 97 gpt = calloc(1, sizeof(*gpt)); 98 SPDK_CU_ASSERT_FATAL(gpt != NULL); 99 gpt->parse_phase = SPDK_GPT_PARSE_PHASE_PRIMARY; 100 gpt->sector_size = 512; 101 102 /* Set *gpt is "aaa..." */ 103 memset(a, 'a', sizeof(a)); 104 gpt->buf = &a[0]; 105 gpt->buf_size = sizeof(a); 106 107 /* Set header_size mismatch */ 108 gpt->sector_size = 512; 109 head = (struct spdk_gpt_header *)(gpt->buf + GPT_PRIMARY_PARTITION_TABLE_LBA * gpt->sector_size); 110 to_le32(&head->header_size, 0x258); 111 re = spdk_gpt_read_header(gpt); 112 CU_ASSERT(re == -1); 113 114 /* Set head->header_size matched, header_crc32 mismatch */ 115 head->header_size = sizeof(*head); 116 to_le32(&head->header_crc32, 0x22D18C80); 117 re = spdk_gpt_read_header(gpt); 118 CU_ASSERT(re == -1); 119 120 /* Set head->header_crc32 matched, gpt_signature mismatch */ 121 to_le32(&head->header_crc32, 0xC5B2117E); 122 re = spdk_gpt_read_header(gpt); 123 CU_ASSERT(re == -1); 124 125 /* Set head->gpt_signature matched, head->my_lba mismatch */ 126 to_le32(&head->header_crc32, 0xD637335A); 127 head->gpt_signature[0] = 'E'; 128 head->gpt_signature[1] = 'F'; 129 head->gpt_signature[2] = 'I'; 130 head->gpt_signature[3] = ' '; 131 head->gpt_signature[4] = 'P'; 132 head->gpt_signature[5] = 'A'; 133 head->gpt_signature[6] = 'R'; 134 head->gpt_signature[7] = 'T'; 135 re = spdk_gpt_read_header(gpt); 136 CU_ASSERT(re == -1); 137 138 /* Set head->my_lba matched, lba_end usable_lba mismatch */ 139 to_le32(&head->header_crc32, 0xB3CDB2D2); 140 to_le64(&head->my_lba, 0x1); 141 re = spdk_gpt_read_header(gpt); 142 CU_ASSERT(re == -1); 143 144 /* Set gpt->lba_end usable_lba matched, passing case */ 145 to_le32(&head->header_crc32, 0x5531F2F0); 146 to_le64(&gpt->lba_start, 0x0); 147 to_le64(&gpt->lba_end, 0x2E935FFE); 148 to_le64(&head->first_usable_lba, 0xA); 149 to_le64(&head->last_usable_lba, 0xF4240); 150 re = spdk_gpt_read_header(gpt); 151 CU_ASSERT(re == 0); 152 153 free(gpt); 154 } 155 156 static void 157 test_read_partitions(void) 158 { 159 struct spdk_gpt *gpt; 160 struct spdk_gpt_header *head; 161 unsigned char a[SPDK_GPT_BUFFER_SIZE]; 162 int re; 163 164 /* spdk_gpt_read_partitions(NULL) does not exist, NULL is filtered out in spdk_gpt_parse_mbr() */ 165 gpt = calloc(1, sizeof(*gpt)); 166 SPDK_CU_ASSERT_FATAL(gpt != NULL); 167 gpt->parse_phase = SPDK_GPT_PARSE_PHASE_PRIMARY; 168 gpt->sector_size = 512; 169 170 /* Set *gpt is "aaa..." */ 171 memset(a, 'a', sizeof(a)); 172 gpt->buf = &a[0]; 173 gpt->buf_size = sizeof(a); 174 175 /* Set num_partition_entries exceeds Max value of entries GPT supported */ 176 gpt->sector_size = 512; 177 head = (struct spdk_gpt_header *)(gpt->buf + GPT_PRIMARY_PARTITION_TABLE_LBA * gpt->sector_size); 178 gpt->header = head; 179 to_le32(&head->num_partition_entries, 0x100); 180 re = spdk_gpt_read_partitions(gpt); 181 CU_ASSERT(re == -1); 182 183 /* Set num_partition_entries within Max value, size_of_partition_entry mismatch */ 184 to_le32(&head->header_crc32, 0x573857BE); 185 to_le32(&head->num_partition_entries, 0x40); 186 to_le32(&head->size_of_partition_entry, 0x0); 187 re = spdk_gpt_read_partitions(gpt); 188 CU_ASSERT(re == -1); 189 190 /* Set size_of_partition_entry matched, partition_entry_lba mismatch */ 191 to_le32(&head->header_crc32, 0x5279B712); 192 to_le32(&head->size_of_partition_entry, 0x80); 193 to_le64(&head->partition_entry_lba, 0x64); 194 re = spdk_gpt_read_partitions(gpt); 195 CU_ASSERT(re == -1); 196 197 /* Set partition_entry_lba matched, partition_entry_array_crc32 mismatch */ 198 to_le32(&head->header_crc32, 0xEC093B43); 199 to_le64(&head->partition_entry_lba, 0x20); 200 to_le32(&head->partition_entry_array_crc32, 0x0); 201 re = spdk_gpt_read_partitions(gpt); 202 CU_ASSERT(re == -1); 203 204 /* Set partition_entry_array_crc32 matched, passing case */ 205 to_le32(&head->header_crc32, 0xE1A08822); 206 to_le32(&head->partition_entry_array_crc32, 0xEBEE44FB); 207 to_le32(&head->num_partition_entries, 0x80); 208 re = spdk_gpt_read_partitions(gpt); 209 CU_ASSERT(re == 0); 210 211 free(gpt); 212 } 213 214 static void 215 test_parse_mbr_and_primary(void) 216 { 217 struct spdk_gpt *gpt; 218 struct spdk_mbr *mbr; 219 struct spdk_gpt_header *head; 220 unsigned char a[SPDK_GPT_BUFFER_SIZE]; 221 int re; 222 223 /* Set gpt is NULL */ 224 re = spdk_gpt_parse_mbr(NULL); 225 CU_ASSERT(re == -1); 226 227 /* Set gpt->buf is NULL */ 228 gpt = calloc(1, sizeof(*gpt)); 229 SPDK_CU_ASSERT_FATAL(gpt != NULL); 230 gpt->parse_phase = SPDK_GPT_PARSE_PHASE_PRIMARY; 231 gpt->sector_size = 512; 232 re = spdk_gpt_parse_mbr(gpt); 233 CU_ASSERT(re == -1); 234 235 /* Set *gpt is "aaa...", check_mbr failed */ 236 memset(a, 'a', sizeof(a)); 237 gpt->buf = &a[0]; 238 gpt->buf_size = sizeof(a); 239 re = spdk_gpt_parse_mbr(gpt); 240 CU_ASSERT(re == -1); 241 242 /* Set check_mbr passed */ 243 mbr = (struct spdk_mbr *)gpt->buf; 244 mbr->mbr_signature = 0xAA55; 245 mbr->partitions[0].start_lba = 1; 246 mbr->partitions[0].os_type = 0xEE; 247 mbr->partitions[0].size_lba = 0xFFFFFFFF; 248 re = spdk_gpt_parse_mbr(gpt); 249 CU_ASSERT(re == 0); 250 251 /* Expect read_header failed */ 252 re = spdk_gpt_parse_partition_table(gpt); 253 CU_ASSERT(re == -1); 254 255 /* Set read_header passed, read_partitions failed */ 256 head = (struct spdk_gpt_header *)(gpt->buf + GPT_PRIMARY_PARTITION_TABLE_LBA * gpt->sector_size); 257 head->header_size = sizeof(*head); 258 head->gpt_signature[0] = 'E'; 259 head->gpt_signature[1] = 'F'; 260 head->gpt_signature[2] = 'I'; 261 head->gpt_signature[3] = ' '; 262 head->gpt_signature[4] = 'P'; 263 head->gpt_signature[5] = 'A'; 264 head->gpt_signature[6] = 'R'; 265 head->gpt_signature[7] = 'T'; 266 to_le32(&head->header_crc32, 0x5531F2F0); 267 to_le64(&head->my_lba, 0x1); 268 to_le64(&gpt->lba_start, 0x0); 269 to_le64(&gpt->lba_end, 0x2E935FFE); 270 to_le64(&head->first_usable_lba, 0xA); 271 to_le64(&head->last_usable_lba, 0xF4240); 272 re = spdk_gpt_parse_partition_table(gpt); 273 CU_ASSERT(re == -1); 274 275 /* Set read_partitions passed, all passed */ 276 to_le32(&head->size_of_partition_entry, 0x80); 277 to_le64(&head->partition_entry_lba, 0x20); 278 to_le32(&head->header_crc32, 0x845A09AA); 279 to_le32(&head->partition_entry_array_crc32, 0xEBEE44FB); 280 to_le32(&head->num_partition_entries, 0x80); 281 re = spdk_gpt_parse_partition_table(gpt); 282 CU_ASSERT(re == 0); 283 284 free(gpt); 285 } 286 287 static void 288 test_parse_secondary(void) 289 { 290 struct spdk_gpt *gpt; 291 struct spdk_gpt_header *head; 292 unsigned char a[SPDK_GPT_BUFFER_SIZE]; 293 int re; 294 295 /* spdk_gpt_parse_partition_table(NULL) does not exist, NULL is filtered out in spdk_gpt_parse_mbr() */ 296 gpt = calloc(1, sizeof(*gpt)); 297 SPDK_CU_ASSERT_FATAL(gpt != NULL); 298 gpt->parse_phase = SPDK_GPT_PARSE_PHASE_SECONDARY; 299 gpt->sector_size = 512; 300 301 /* Set *gpt is "aaa...", read_header failed */ 302 memset(a, 'a', sizeof(a)); 303 gpt->buf = &a[0]; 304 gpt->buf_size = sizeof(a); 305 re = spdk_gpt_parse_partition_table(gpt); 306 CU_ASSERT(re == -1); 307 308 /* Set read_header passed, read_partitions failed */ 309 head = (struct spdk_gpt_header *)(gpt->buf + gpt->buf_size - gpt->sector_size); 310 head->header_size = sizeof(*head); 311 head->gpt_signature[0] = 'E'; 312 head->gpt_signature[1] = 'F'; 313 head->gpt_signature[2] = 'I'; 314 head->gpt_signature[3] = ' '; 315 head->gpt_signature[4] = 'P'; 316 head->gpt_signature[5] = 'A'; 317 head->gpt_signature[6] = 'R'; 318 head->gpt_signature[7] = 'T'; 319 to_le32(&head->header_crc32, 0xAA68A167); 320 to_le64(&head->my_lba, 0x63FFFFF); 321 to_le64(&gpt->lba_start, 0x0); 322 to_le64(&gpt->lba_end, 0x63FFFFF); 323 to_le64(&gpt->total_sectors, 0x6400000); 324 to_le64(&head->first_usable_lba, 0xA); 325 to_le64(&head->last_usable_lba, 0x63FFFDE); 326 re = spdk_gpt_parse_partition_table(gpt); 327 CU_ASSERT(re == -1); 328 329 /* Set read_partitions passed, all passed */ 330 to_le32(&head->size_of_partition_entry, 0x80); 331 to_le64(&head->partition_entry_lba, 0x63FFFDF); 332 to_le32(&head->header_crc32, 0x204129E8); 333 to_le32(&head->partition_entry_array_crc32, 0xEBEE44FB); 334 to_le32(&head->num_partition_entries, 0x80); 335 re = spdk_gpt_parse_partition_table(gpt); 336 CU_ASSERT(re == 0); 337 338 free(gpt); 339 } 340 341 int 342 main(int argc, char **argv) 343 { 344 CU_pSuite suite = NULL; 345 unsigned int num_failures; 346 347 CU_set_error_action(CUEA_ABORT); 348 CU_initialize_registry(); 349 350 suite = CU_add_suite("gpt_parse", NULL, NULL); 351 352 CU_ADD_TEST(suite, test_parse_mbr_and_primary); 353 CU_ADD_TEST(suite, test_parse_secondary); 354 CU_ADD_TEST(suite, test_check_mbr); 355 CU_ADD_TEST(suite, test_read_header); 356 CU_ADD_TEST(suite, test_read_partitions); 357 358 CU_basic_set_mode(CU_BRM_VERBOSE); 359 CU_basic_run_tests(); 360 num_failures = CU_get_number_of_failures(); 361 CU_cleanup_registry(); 362 return num_failures; 363 } 364