Changeset d617050 in mainline for uspace/lib/gpt/libgpt.c
- Timestamp:
- 2013-04-20T01:13:44Z (12 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 8f6c7785
- Parents:
- e91d17a
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/gpt/libgpt.c
re91d17a rd617050 56 56 static int reduce_part_array(gpt_partitions_t * p); 57 57 static long long nearest_larger_int(double a); 58 static int gpt_memcmp(const void * a, const void * b, size_t len); 58 59 59 60 /** Read GPT from specific device 60 61 * @param dev_handle device to read GPT from 61 * 62 * 62 63 * @return GPT record on success, NULL on error 63 64 */ … … 66 67 int rc; 67 68 size_t b_size; 68 69 69 70 rc = block_get_bsize(dev_handle, &b_size); 70 71 if (rc != EOK) { … … 72 73 return NULL; 73 74 } 74 75 75 76 gpt_t * gpt = malloc(sizeof(gpt_t)); 76 77 if (gpt == NULL) { … … 78 79 return NULL; 79 80 } 80 81 81 82 gpt->raw_data = malloc(b_size);// We might need only sizeof(gpt_header_t), 82 if (gpt == NULL) { // but we should follow specs and have 83 if (gpt == NULL) { // but we should follow specs and have 83 84 free(gpt); // zeroes through all the rest of the block 84 85 errno = ENOMEM; 85 86 return NULL; 86 87 } 87 88 88 89 89 90 rc = load_and_check_header(dev_handle, GPT_HDR_BA, b_size, gpt->raw_data); 90 91 if (rc == EBADCHECKSUM || rc == EINVAL) { … … 95 96 goto fail; 96 97 } 97 98 98 99 rc = load_and_check_header(dev_handle, n_blocks - 1, b_size, gpt->raw_data); 99 100 if (rc == EBADCHECKSUM || rc == EINVAL) { … … 102 103 } 103 104 } 104 105 105 106 gpt->device = dev_handle; 106 107 107 108 return gpt; 108 109 … … 115 116 * @param header GPT header to be written 116 117 * @param dev_handle device handle to write the data to 117 * 118 * 118 119 * @return 0 on success, libblock error code otherwise 119 * 120 * 120 121 * Note: Firstly write partitions (if changed), then gpt header. 121 122 */ … … 124 125 int rc; 125 126 size_t b_size; 126 127 127 128 gpt->raw_data->header_crc32 = 0; 128 129 gpt->raw_data->header_crc32 = compute_crc32((uint8_t *) gpt->raw_data, 129 130 uint32_t_le2host(gpt->raw_data->header_size)); 130 131 131 132 rc = block_get_bsize(dev_handle, &b_size); 132 133 if (rc != EOK) 133 134 return rc; 134 135 135 136 rc = block_init(EXCHANGE_ATOMIC, dev_handle, b_size); 136 137 if (rc != EOK) 137 138 return rc; 138 139 139 140 /* Write to main GPT header location */ 140 141 rc = block_write_direct(dev_handle, GPT_HDR_BA, GPT_HDR_BS, gpt->raw_data); … … 142 143 block_fini(dev_handle); 143 144 return rc; 144 145 145 146 aoff64_t n_blocks; 146 147 rc = block_get_nblocks(dev_handle, &n_blocks); 147 148 if (rc != EOK) 148 149 return rc; 149 150 150 151 /* Write to backup GPT header location */ 151 152 //FIXME: those idiots thought it would be cool to have these fields in reverse order... … … 154 155 if (rc != EOK) 155 156 return rc; 156 157 157 158 return 0; 158 159 } … … 160 161 /** Parse partitions from GPT 161 162 * @param gpt GPT to be parsed 162 * 163 * 163 164 * @return partition linked list pointer or NULL on error 164 165 * error code is stored in errno … … 172 173 uint32_t ent_size = uint32_t_le2host(gpt->raw_data->entry_size); 173 174 uint64_t ent_lba = uint64_t_le2host(gpt->raw_data->entry_lba); 174 175 175 176 res = alloc_part_array(fill); 176 177 if (res == NULL) { … … 178 179 return NULL; 179 180 } 180 181 181 182 /* We can limit comm_size like this: 182 183 * - we don't need more bytes … … 188 189 return NULL; 189 190 } 190 191 191 192 size_t block_size; 192 193 rc = block_get_bsize(gpt->device, &block_size); … … 196 197 return NULL; 197 198 } 198 199 199 200 //size_t bufpos = 0; 200 201 //size_t buflen = 0; 201 202 aoff64_t pos = ent_lba * block_size; 202 203 203 204 /* Now we read just sizeof(gpt_entry_t) bytes for each entry from the device. 204 205 * Hopefully, this does not bypass cache (no mention in libblock.c), … … 212 213 //rc = block_seqread(gpt->device, &bufpos, &buflen, &pos, res->part_array[i], sizeof(gpt_entry_t)); 213 214 pos += ent_size; 214 215 215 216 if (rc != EOK) { 216 217 gpt_free_partitions(res); … … 219 220 } 220 221 } 221 222 222 223 /* FIXME: so far my boasting about variable partition entry size 223 224 * will not work. The CRC32 checksums will be different. … … 226 227 */ 227 228 uint32_t crc = compute_crc32((uint8_t *) res->part_array, res->fill * sizeof(gpt_entry_t)); 228 229 229 230 if(uint32_t_le2host(gpt->raw_data->pe_array_crc32) != crc) 230 231 { … … 233 234 return NULL; 234 235 } 235 236 236 237 return res; 237 238 } … … 241 242 * @param header GPT header belonging to the 'parts' partitions 242 243 * @param dev_handle device to write the data to 243 * 244 * 244 245 * @return returns EOK on succes, specific error code otherwise 245 246 */ … … 248 249 int rc; 249 250 size_t b_size; 250 251 251 252 gpt->raw_data->pe_array_crc32 = compute_crc32((uint8_t *) parts->part_array, parts->fill * gpt->raw_data->entry_size); 252 253 253 254 rc = block_get_bsize(dev_handle, &b_size); 254 255 if (rc != EOK) 255 256 return rc; 256 257 257 258 rc = block_init(EXCHANGE_ATOMIC, dev_handle, b_size); 258 259 if (rc != EOK) 259 260 return rc; 260 261 261 262 /* Write to main GPT partition array location */ 262 rc = block_write_direct(dev_handle, uint64_t_le2host(gpt->raw_data->entry_lba), 263 nearest_larger_int((uint64_t_le2host(gpt->raw_data->entry_size) * parts->fill) / b_size), 263 rc = block_write_direct(dev_handle, uint64_t_le2host(gpt->raw_data->entry_lba), 264 nearest_larger_int((uint64_t_le2host(gpt->raw_data->entry_size) * parts->fill) / b_size), 264 265 parts->part_array); 265 266 if (rc != EOK) 266 267 block_fini(dev_handle); 267 268 return rc; 268 269 269 270 aoff64_t n_blocks; 270 271 rc = block_get_nblocks(dev_handle, &n_blocks); 271 272 if (rc != EOK) 272 273 return rc; 273 274 274 275 /* Write to backup GPT partition array location */ 275 276 //rc = block_write_direct(dev_handle, n_blocks - 1, GPT_HDR_BS, header->raw_data); … … 277 278 if (rc != EOK) 278 279 return rc; 279 280 280 281 281 282 return gpt_write_gpt_header(gpt, dev_handle); 282 283 } 283 284 284 285 /** Alloc new partition 285 * 286 * 286 287 * @param parts partition table to carry new partition 287 * 288 * 288 289 * @return returns pointer to the new partition or NULL on ENOMEM 289 * 290 * 290 291 * Note: use either gpt_alloc_partition or gpt_add_partition. The first 291 * returns a pointer to write your data to, the second copies the data 292 * returns a pointer to write your data to, the second copies the data 292 293 * (and does not free the memory). 293 294 */ … … 298 299 return NULL; 299 300 } 300 301 301 302 return parts->part_array + parts->fill++; 302 303 } 303 304 304 305 /** Copy partition into partition array 305 * 306 * 306 307 * @param parts target partition array 307 308 * @param partition source partition to copy 308 * 309 * 309 310 * @return -1 on error, 0 otherwise 310 * 311 * 311 312 * Note: use either gpt_alloc_partition or gpt_add_partition. The first 312 * returns a pointer to write your data to, the second copies the data 313 * returns a pointer to write your data to, the second copies the data 313 314 * (and does not free the memory). 314 315 */ … … 317 318 if (parts->fill == parts->arr_size) { 318 319 if (extend_part_array(parts) == -1) 319 return -1;320 return ENOMEM; 320 321 } 321 322 extend_part_array(parts); 322 return parts;323 return EOK;; 323 324 } 324 325 325 326 /** Remove partition from array 326 * 327 * 327 328 * @param idx index of the partition to remove 328 * 329 * 329 330 * @return -1 on error, 0 otherwise 330 * 331 * 331 332 * Note: even if it fails, the partition still gets removed. Only 332 333 * reducing the array failed. … … 335 336 { 336 337 if (idx != parts->fill - 1) { 337 memcpy(parts->part_array + idx, parts->part_array + fill - 1, sizeof(gpt_entry_t));338 memcpy(parts->part_array + idx, parts->part_array + parts->fill - 1, sizeof(gpt_entry_t)); 338 339 parts->fill -= 1; 339 340 } 340 341 341 342 if (parts->fill < (parts->arr_size / 2) - GPT_IGNORE_FILL_NUM) { 342 343 if (reduce_part_array(parts) == -1) 343 344 return -1; 344 345 } 345 346 346 347 return 0; 347 348 } … … 355 356 356 357 /** Free partition list 357 * 358 * 358 359 * @param parts partition list to be freed 359 360 */ … … 371 372 size_t i; 372 373 for (i = 0; gpt_ptypes[i].guid != NULL; i++) { 373 if ( memcmp(p->raw_data.part_type, gpt_ptypes[i].guid, 16) == 0) {374 if (gpt_memcmp(p->part_type, gpt_ptypes[i].guid, 16) == 0) { 374 375 break; 375 376 } … … 381 382 * @param p partition to be set 382 383 * @param type partition type to set 383 * - see gpt_ptypes to choose from 384 * 385 */ 386 void gpt_set_part_type(gpt_part_t * p, int type) 384 * - see our fine selection at gpt_ptypes to choose from 385 */ 386 void gpt_set_part_type(gpt_part_t * p, size_t type) 387 387 { 388 388 /* Beware: first 3 blocks are byteswapped! */ 389 p->raw_data.part_type[3] = gpt_ptypes[type].guid[0]; 390 p->raw_data.part_type[2] = gpt_ptypes[type].guid[1]; 391 p->raw_data.part_type[1] = gpt_ptypes[type].guid[2]; 392 p->raw_data.part_type[0] = gpt_ptypes[type].guid[3]; 393 394 p->raw_data.part_type[5] = gpt_ptypes[type].guid[4]; 395 p->raw_data.part_type[4] = gpt_ptypes[type].guid[5]; 396 397 p->raw_data.part_type[7] = gpt_ptypes[type].guid[6]; 398 p->raw_data.part_type[6] = gpt_ptypes[type].guid[7]; 399 400 p->raw_data.part_type[8] = gpt_ptypes[type].guid[8]; 401 p->raw_data.part_type[9] = gpt_ptypes[type].guid[9]; 402 p->raw_data.part_type[10] = gpt_ptypes[type].guid[10]; 403 p->raw_data.part_type[11] = gpt_ptypes[type].guid[11]; 404 p->raw_data.part_type[12] = gpt_ptypes[type].guid[12]; 405 p->raw_data.part_type[13] = gpt_ptypes[type].guid[13]; 406 p->raw_data.part_type[14] = gpt_ptypes[type].guid[14]; 407 p->raw_data.part_type[15] = gpt_ptypes[type].guid[15]; 408 } 409 410 char * gpt_get_part_name(gpt_entry_t * p) 411 { 412 return p->raw_data.part_name; 389 p->part_type[3] = gpt_ptypes[type].guid[0]; 390 p->part_type[2] = gpt_ptypes[type].guid[1]; 391 p->part_type[1] = gpt_ptypes[type].guid[2]; 392 p->part_type[0] = gpt_ptypes[type].guid[3]; 393 394 p->part_type[5] = gpt_ptypes[type].guid[4]; 395 p->part_type[4] = gpt_ptypes[type].guid[5]; 396 397 p->part_type[7] = gpt_ptypes[type].guid[6]; 398 p->part_type[6] = gpt_ptypes[type].guid[7]; 399 400 p->part_type[8] = gpt_ptypes[type].guid[8]; 401 p->part_type[9] = gpt_ptypes[type].guid[9]; 402 p->part_type[10] = gpt_ptypes[type].guid[10]; 403 p->part_type[11] = gpt_ptypes[type].guid[11]; 404 p->part_type[12] = gpt_ptypes[type].guid[12]; 405 p->part_type[13] = gpt_ptypes[type].guid[13]; 406 p->part_type[14] = gpt_ptypes[type].guid[14]; 407 p->part_type[15] = gpt_ptypes[type].guid[15]; 408 } 409 410 /** Get partition starting LBA */ 411 uint64_t gpt_get_start_lba(gpt_part_t * p) 412 { 413 return uint64_t_le2host(p->start_lba); 414 } 415 416 /** Set partition starting LBA */ 417 void gpt_set_start_lba(gpt_part_t * p, uint64_t start) 418 { 419 p->start_lba = host2uint64_t_le(start); 420 } 421 422 /** Get partition ending LBA */ 423 uint64_t gpt_get_end_lba(gpt_part_t * p) 424 { 425 return uint64_t_le2host(p->end_lba); 426 } 427 428 /** Set partition ending LBA */ 429 void gpt_set_end_lba(gpt_part_t * p, uint64_t end) 430 { 431 p->end_lba = host2uint64_t_le(end); 432 } 433 434 435 unsigned char * gpt_get_part_name(gpt_part_t * p) 436 { 437 return p->part_name; 413 438 } 414 439 415 440 /** Copy partition name */ 416 void gpt_set_part_name(gpt_ entry_t * p, char * name[], size_t length)441 void gpt_set_part_name(gpt_part_t * p, char * name[], size_t length) 417 442 { 418 443 if (length >= 72) 419 444 length = 71; 420 445 421 446 memcpy(p->part_name, name, length); 422 447 p->part_name[length] = '\0'; … … 424 449 425 450 /** Get partition attribute */ 426 externbool gpt_get_flag(gpt_part_t * p, GPT_ATTR flag)427 { 428 return (p-> raw_data.attributes & (((uint64_t) 1) << flag)) ? 1 : 0;451 bool gpt_get_flag(gpt_part_t * p, GPT_ATTR flag) 452 { 453 return (p->attributes & (((uint64_t) 1) << flag)) ? 1 : 0; 429 454 } 430 455 431 456 /** Set partition attribute */ 432 externvoid gpt_set_flag(gpt_part_t * p, GPT_ATTR flag, bool value)433 { 434 uint64_t attr = p-> raw_data.attributes;457 void gpt_set_flag(gpt_part_t * p, GPT_ATTR flag, bool value) 458 { 459 uint64_t attr = p->attributes; 435 460 436 461 if (value) … … 439 464 attr = attr ^ (attr & (((uint64_t) 1) << flag)); 440 465 441 p-> raw_data.attributes = attr;466 p->attributes = attr; 442 467 } 443 468 … … 447 472 { 448 473 int rc; 449 474 450 475 rc = block_init(EXCHANGE_ATOMIC, dev_handle, b_size); 451 476 if (rc != EOK) 452 477 return rc; 453 478 454 479 rc = block_read_direct(dev_handle, addr, GPT_HDR_BS, header); 455 480 block_fini(dev_handle); 456 481 if (rc != EOK) 457 482 return rc; 458 459 483 484 460 485 unsigned int i; 461 486 /* Check the EFI signature */ … … 464 489 return EINVAL; 465 490 } 466 491 467 492 /* Check the CRC32 of the header */ 468 493 uint32_t crc = header->header_crc32; … … 472 497 else 473 498 header->header_crc32 = crc; 474 499 475 500 /* Check for zeroes in the rest of the block */ 476 501 for (i = sizeof(gpt_header_t); i < b_size; ++i) { … … 478 503 return EINVAL; 479 504 } 480 505 481 506 return EOK; 482 507 } … … 489 514 return NULL; 490 515 } 491 516 492 517 uint32_t size = num > GPT_BASE_PART_NUM ? num : GPT_BASE_PART_NUM; 493 518 res->part_array = malloc(size * sizeof(gpt_entry_t)); … … 497 522 return NULL; 498 523 } 499 524 500 525 res->fill = num; 501 526 res->arr_size = size; 502 527 503 528 return res; 504 529 } … … 512 537 return -1; 513 538 } 514 539 515 540 memcpy(tmp, p->part_array, p->fill); 516 541 free(p->part_array); 517 542 p->part_array = tmp; 518 543 p->arr_size = nsize; 519 544 520 545 return 0; 521 546 } … … 530 555 return -1; 531 556 } 532 557 533 558 memcpy(tmp, p->part_array, p->fill < nsize ? p->fill : nsize); 534 559 free(p->part_array); … … 536 561 p->arr_size = nsize; 537 562 } 538 563 539 564 return 0; 540 565 } … … 546 571 return (long long) a; 547 572 } 548 573 549 574 return ((long long) a) + 1; 550 575 } 551 576 552 553 554 577 static int gpt_memcmp(const void * a, const void * b, size_t len) 578 { 579 size_t i; 580 int diff; 581 const unsigned char * x = a; 582 const unsigned char * y = b; 583 584 for (i = 0; i < len; i++) { 585 diff = (int)*(x++) - (int)*(y++); 586 if (diff != 0) { 587 return diff; 588 } 589 } 590 return 0; 591 } 592 593 594 595
Note:
See TracChangeset
for help on using the changeset viewer.