Changeset bf7ddde in mainline
- Timestamp:
- 2015-07-08T17:19:26Z (9 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 70815a24
- Parents:
- 603c1d1f
- Location:
- uspace/lib/label
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/label/include/types/liblabel.h
r603c1d1f rbf7ddde 112 112 typedef struct { 113 113 uint64_t hdr_ba[2]; 114 uint32_t hdr_size; 114 115 uint64_t ptable_ba[2]; 116 uint64_t pt_blocks; 115 117 size_t esize; 118 uint32_t pt_crc; 116 119 } label_gpt_t; 117 120 -
uspace/lib/label/src/gpt.c
r603c1d1f rbf7ddde 34 34 */ 35 35 36 #include <adt/checksum.h> 36 37 #include <block.h> 37 38 #include <byteorder.h> … … 58 59 static int gpt_pte_to_part(label_t *, gpt_entry_t *, int); 59 60 static int gpt_pte_update(label_t *, gpt_entry_t *, int); 61 62 static int gpt_update_pt_crc(label_t *, uint32_t); 63 static void gpt_hdr_compute_crc(gpt_header_t *, size_t); 64 static int gpt_hdr_get_crc(gpt_header_t *, size_t, uint32_t *); 60 65 61 66 const uint8_t efi_signature[8] = { … … 82 87 gpt_header_t *gpt_hdr[2]; 83 88 gpt_entry_t *eptr; 84 uint8_t *etable = NULL;89 uint8_t *etable[2]; 85 90 size_t bsize; 86 91 uint32_t num_entries; 87 92 uint32_t esize; 88 uint32_t bcnt;93 uint32_t pt_blocks; 89 94 uint64_t ptba[2]; 90 95 uint64_t h1ba; 91 96 uint32_t entry; 97 uint32_t pt_crc; 92 98 uint64_t ba_min, ba_max; 99 uint32_t hdr_size; 100 uint32_t hdr_crc; 93 101 int i, j; 94 102 int rc; … … 96 104 gpt_hdr[0] = NULL; 97 105 gpt_hdr[1] = NULL; 106 etable[0] = NULL; 107 etable[1] = NULL; 98 108 99 109 rc = block_get_bsize(sid, &bsize); … … 149 159 } 150 160 161 if (uint32_t_le2host(gpt_hdr[0]->revision) != 162 uint32_t_le2host(gpt_hdr[1]->revision)) { 163 rc = EINVAL; 164 goto error; 165 } 166 167 if (uint32_t_le2host(gpt_hdr[0]->header_size) != 168 uint32_t_le2host(gpt_hdr[1]->header_size)) { 169 rc = EINVAL; 170 goto error; 171 } 172 173 hdr_size = uint32_t_le2host(gpt_hdr[0]->header_size); 174 if (hdr_size < sizeof(gpt_header_t) || 175 hdr_size > bsize) { 176 rc = EINVAL; 177 goto error; 178 } 179 180 for (j = 0; j < 2; j++) { 181 rc = gpt_hdr_get_crc(gpt_hdr[j], hdr_size, &hdr_crc); 182 if (rc != EOK) 183 goto error; 184 185 if (uint32_t_le2host(gpt_hdr[j]->header_crc32) != hdr_crc) { 186 rc = EINVAL; 187 goto error; 188 } 189 } 190 191 if (uint64_t_le2host(gpt_hdr[0]->my_lba) != gpt_hdr_ba) { 192 rc = EINVAL; 193 goto error; 194 } 195 196 if (uint64_t_le2host(gpt_hdr[1]->my_lba) != h1ba) { 197 rc = EINVAL; 198 goto error; 199 } 200 201 if (uint64_t_le2host(gpt_hdr[1]->alternate_lba) != gpt_hdr_ba) { 202 rc = EINVAL; 203 goto error; 204 } 205 151 206 num_entries = uint32_t_le2host(gpt_hdr[0]->num_entries); 152 207 esize = uint32_t_le2host(gpt_hdr[0]->entry_size); 153 bcnt = (num_entries + esize - 1) / esize;208 pt_blocks = (num_entries * esize + bsize - 1) / bsize; 154 209 ptba[0] = uint64_t_le2host(gpt_hdr[0]->entry_lba); 155 210 ptba[1] = uint64_t_le2host(gpt_hdr[1]->entry_lba); 156 211 ba_min = uint64_t_le2host(gpt_hdr[0]->first_usable_lba); 157 212 ba_max = uint64_t_le2host(gpt_hdr[0]->last_usable_lba); 213 pt_crc = uint32_t_le2host(gpt_hdr[0]->pe_array_crc32); 214 215 if (uint64_t_le2host(gpt_hdr[1]->first_usable_lba) != ba_min) { 216 rc = EINVAL; 217 goto error; 218 } 219 220 if (uint64_t_le2host(gpt_hdr[1]->last_usable_lba) != ba_max) { 221 rc = EINVAL; 222 goto error; 223 } 224 225 for (i = 0; i < 16; i++) { 226 if (gpt_hdr[1]->disk_guid[i] != gpt_hdr[0]->disk_guid[i]) { 227 rc = EINVAL; 228 goto error; 229 } 230 } 231 232 if (uint32_t_le2host(gpt_hdr[1]->num_entries) != num_entries) { 233 rc = EINVAL; 234 goto error; 235 } 236 237 if (uint32_t_le2host(gpt_hdr[1]->entry_size) != esize) { 238 rc = EINVAL; 239 goto error; 240 } 158 241 159 242 if (num_entries < 1) { … … 172 255 } 173 256 174 etable = calloc(num_entries, esize); 175 if (etable == NULL) { 176 rc = ENOMEM; 177 goto error; 178 } 179 180 rc = block_read_direct(sid, ptba[0], bcnt, etable); 181 if (rc != EOK) { 182 rc = EIO; 183 goto error; 184 } 185 186 for (entry = 0; entry < num_entries; entry++) { 187 eptr = (gpt_entry_t *)(etable + entry * esize); 188 rc = gpt_pte_to_part(label, eptr, entry + 1); 189 if (rc != EOK) 190 goto error; 191 } 192 193 free(etable); 194 etable = NULL; 257 /* Check fields in backup header for validity */ 258 259 for (j = 0; j < 2; j++) { 260 etable[j] = calloc(1, pt_blocks * bsize); 261 if (etable[j] == NULL) { 262 rc = ENOMEM; 263 goto error; 264 } 265 266 rc = block_read_direct(sid, ptba[j], pt_blocks / 2, etable[j]); 267 if (rc != EOK) { 268 rc = EIO; 269 goto error; 270 } 271 272 if (compute_crc32(etable[j], num_entries * esize) != pt_crc) { 273 rc = EIO; 274 goto error; 275 } 276 277 for (entry = 0; entry < num_entries; entry++) { 278 eptr = (gpt_entry_t *)(etable[j] + entry * esize); 279 rc = gpt_pte_to_part(label, eptr, entry + 1); 280 if (rc != EOK) 281 goto error; 282 } 283 } 284 285 free(etable[0]); 286 etable[0] = NULL; 287 free(etable[1]); 288 etable[1] = NULL; 195 289 free(gpt_hdr[0]); 196 290 gpt_hdr[0] = NULL; … … 211 305 label->lt.gpt.ptable_ba[1] = ptba[1]; 212 306 label->lt.gpt.esize = esize; 307 label->lt.gpt.pt_blocks = pt_blocks; 308 label->lt.gpt.pt_crc = pt_crc; 309 label->lt.gpt.hdr_size = hdr_size; 213 310 214 311 *rlabel = label; 215 312 return EOK; 216 313 error: 217 free(etable); 314 free(etable[0]); 315 free(etable[1]); 218 316 free(gpt_hdr[0]); 219 317 free(gpt_hdr[1]); … … 236 334 aoff64_t nblocks; 237 335 uint64_t resv_blocks; 336 uint32_t pt_crc; 238 337 int i, j; 239 338 int rc; … … 277 376 278 377 for (i = 0; i < 2; i++) { 378 etable = calloc(1, pt_blocks * bsize); 379 if (etable == NULL) { 380 rc = ENOMEM; 381 goto error; 382 } 383 384 rc = block_write_direct(sid, ptba[i], pt_blocks, etable); 385 if (rc != EOK) { 386 rc = EIO; 387 goto error; 388 } 389 390 pt_crc = compute_crc32((uint8_t *)etable, 391 num_entries * esize); 392 393 free(etable); 394 etable = NULL; 395 279 396 gpt_hdr = calloc(1, bsize); 280 397 if (gpt_hdr == NULL) { … … 287 404 gpt_hdr->revision = host2uint32_t_le(gpt_revision); 288 405 gpt_hdr->header_size = host2uint32_t_le(sizeof(gpt_header_t)); 289 gpt_hdr->header_crc32 = 0; /* XXX */406 gpt_hdr->header_crc32 = 0; 290 407 gpt_hdr->my_lba = host2uint64_t_le(hdr_ba[i]); 291 408 gpt_hdr->alternate_lba = host2uint64_t_le(hdr_ba[1 - i]); 292 409 gpt_hdr->first_usable_lba = host2uint64_t_le(ba_min); 293 410 gpt_hdr->last_usable_lba = host2uint64_t_le(ba_max); 294 //gpt_hdr->disk_guid 411 //gpt_hdr->disk_guid XXX 295 412 gpt_hdr->entry_lba = host2uint64_t_le(ptba[i]); 296 413 gpt_hdr->num_entries = host2uint32_t_le(num_entries); 297 414 gpt_hdr->entry_size = host2uint32_t_le(esize); 298 gpt_hdr->pe_array_crc32 = 0; /* XXXX */ 415 gpt_hdr->pe_array_crc32 = pt_crc; 416 417 gpt_hdr_compute_crc(gpt_hdr, sizeof(gpt_header_t)); 299 418 300 419 rc = block_write_direct(sid, hdr_ba[i], 1, gpt_hdr); … … 306 425 free(gpt_hdr); 307 426 gpt_hdr = NULL; 308 309 etable = calloc(num_entries, esize);310 if (etable == NULL) {311 rc = ENOMEM;312 goto error;313 }314 315 rc = block_write_direct(sid, ptba[i], pt_blocks, etable);316 if (rc != EOK) {317 rc = EIO;318 goto error;319 }320 321 free(etable);322 etable = 0;323 427 } 324 428 … … 342 446 label->lt.gpt.ptable_ba[1] = ptba[1]; 343 447 label->lt.gpt.esize = esize; 448 label->lt.gpt.pt_blocks = pt_blocks; 449 label->lt.gpt.hdr_size = sizeof(gpt_header_t); 344 450 345 451 *rlabel = label; … … 371 477 uint8_t *etable = NULL; 372 478 label_part_t *part; 373 uint64_t pt_blocks;374 479 int i; 375 480 int rc; … … 380 485 goto error; 381 486 } 382 383 pt_blocks = label->pri_entries * label->lt.gpt.esize /384 label->block_size;385 487 386 488 for (i = 0; i < 2; i++) { … … 401 503 gpt_hdr = NULL; 402 504 403 etable = calloc(label->pri_entries, label->lt.gpt.esize); 505 etable = calloc(1, label->lt.gpt.pt_blocks * 506 label->block_size); 404 507 if (etable == NULL) { 405 508 rc = ENOMEM; … … 408 511 409 512 rc = block_write_direct(label->svc_id, 410 label->lt.gpt.ptable_ba[i], pt_blocks, etable); 513 label->lt.gpt.ptable_ba[i], label->lt.gpt.pt_blocks, 514 etable); 411 515 if (rc != EOK) { 412 516 rc = EIO; … … 596 700 { 597 701 size_t pos; 598 size_t offs;599 702 uint64_t ba; 703 uint64_t nblocks; 704 size_t ptbytes; 600 705 uint8_t *buf; 601 706 gpt_entry_t *e; 707 uint32_t crc; 602 708 int i; 603 709 int rc; 604 710 711 /* Byte offset of partition entry */ 605 712 pos = index * label->lt.gpt.esize; 606 offs = pos % label->block_size; 607 608 buf = calloc(1, label->block_size); 713 /* Number of bytes in partition table */ 714 ptbytes = label->pri_entries * label->lt.gpt.esize; 715 716 buf = calloc(1, label->block_size * label->lt.gpt.pt_blocks); 609 717 if (buf == NULL) 610 718 return ENOMEM; … … 612 720 /* For both partition tables: read, modify, write */ 613 721 for (i = 0; i < 2; i++) { 614 ba = label->lt.gpt.ptable_ba[i] + 615 pos / label->block_size; 616 617 rc = block_read_direct(label->svc_id, ba, 1, buf); 618 if (rc != EOK) { 722 ba = label->lt.gpt.ptable_ba[i]; 723 nblocks = label->lt.gpt.pt_blocks; 724 725 rc = block_read_direct(label->svc_id, ba, nblocks, buf); 726 if (rc != EOK) { 727 rc = EIO; 728 goto error; 729 } 730 731 crc = compute_crc32(buf, ptbytes); 732 if (crc != label->lt.gpt.pt_crc) { 733 /* Corruption detected */ 619 734 rc = EIO; 620 735 goto error; … … 622 737 623 738 /* Replace single entry */ 624 e = (gpt_entry_t *)(&buf[ offs]);739 e = (gpt_entry_t *)(&buf[pos]); 625 740 *e = *pte; 626 741 627 rc = block_write_direct(label->svc_id, ba, 1, buf); 742 rc = block_write_direct(label->svc_id, ba, nblocks, buf); 743 if (rc != EOK) { 744 rc = EIO; 745 goto error; 746 } 747 748 crc = compute_crc32(buf, ptbytes); 749 rc = gpt_update_pt_crc(label, crc); 628 750 if (rc != EOK) { 629 751 rc = EIO; … … 639 761 } 640 762 763 static int gpt_update_pt_crc(label_t *label, uint32_t crc) 764 { 765 gpt_header_t *gpt_hdr; 766 int rc; 767 int i; 768 769 gpt_hdr = calloc(1, label->block_size); 770 if (gpt_hdr == NULL) { 771 rc = ENOMEM; 772 goto error; 773 } 774 775 for (i = 0; i < 2; i++) { 776 rc = block_read_direct(label->svc_id, 777 label->lt.gpt.hdr_ba[i], 1, gpt_hdr); 778 if (rc != EOK) { 779 rc = EIO; 780 goto error; 781 } 782 783 gpt_hdr->pe_array_crc32 = host2uint32_t_le(crc); 784 gpt_hdr_compute_crc(gpt_hdr, label->lt.gpt.hdr_size); 785 786 rc = block_write_direct(label->svc_id, 787 label->lt.gpt.hdr_ba[i], 1, gpt_hdr); 788 if (rc != EOK) { 789 rc = EIO; 790 goto error; 791 } 792 } 793 794 free(gpt_hdr); 795 return EOK; 796 error: 797 return rc; 798 } 799 800 static void gpt_hdr_compute_crc(gpt_header_t *hdr, size_t hdr_size) 801 { 802 uint32_t crc; 803 804 hdr->header_crc32 = 0; 805 crc = compute_crc32((uint8_t *)hdr, hdr_size); 806 hdr->header_crc32 = crc; 807 } 808 809 static int gpt_hdr_get_crc(gpt_header_t *hdr, size_t hdr_size, uint32_t *crc) 810 { 811 gpt_header_t *c; 812 813 c = calloc(1, sizeof(gpt_header_t)); 814 if (c == NULL) 815 return ENOMEM; 816 817 memcpy(c, hdr, hdr_size); 818 c->header_crc32 = 0; 819 *crc = compute_crc32((uint8_t *)c, hdr_size); 820 free(c); 821 822 return EOK; 823 } 824 641 825 /** @} 642 826 */
Note:
See TracChangeset
for help on using the changeset viewer.