Changeset d617050 in mainline
- 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
- Location:
- uspace/lib
- Files:
-
- 4 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 -
uspace/lib/gpt/libgpt.h
re91d17a rd617050 102 102 } __attribute__((packed)) gpt_entry_t; 103 103 104 typedef struct g_part { 105 /** Partition entry is in use */ 106 bool present; 107 /** Address of first block */ 108 aoff64_t start_addr; 109 /** Number of blocks */ 110 aoff64_t length; 111 /** Raw data access */ 112 gpt_entry_t raw_data; //TODO: a pointer or just a member? 113 }gpt_part_t; 104 105 //typedef struct g_part { 106 ///** Partition entry is in use **/ 107 //bool present; 108 ///** Address of first block */ 109 //aoff64_t start_addr; 110 ///** Number of blocks */ 111 //aoff64_t length; 112 ///** Raw data access */ 113 //gpt_entry_t raw_data; //TODO: a pointer or just a member? 114 //}gpt_part_t; 115 typedef gpt_entry_t gpt_part_t; 116 114 117 115 118 typedef struct gpt_parts { … … 140 143 extern int gpt_write_gpt_header(gpt_t * header, service_id_t dev_handle); 141 144 142 extern gpt_partitions_t * gpt_read_partitions(gpt_t * gpt); 143 extern int gpt_write_partitions(gpt_partitions_t * parts, gpt_t * header, service_id_t dev_handle); 144 extern gpt_part_t * gpt_alloc_partition(gpt_partitions_t * parts); 145 extern int gpt_add_partition(gpt_partitions_t * parts, gpt_part_t * partition); 146 extern int gpt_remove_partition(gpt_partitions_t * parts, size_t idx); 147 extern size_t gpt_get_part_type(gpt_part_t * p); 148 extern void gpt_set_part_type(gpt_part_t * p, size_t type); 149 extern char * gpt_get_part_name(gpt_entry_t * p); 150 extern void gpt_set_part_name(gpt_entry_t * p, char * name[], size_t length); 151 extern bool gpt_get_flag(gpt_part_t * p, GPT_ATTR flag); 152 extern void gpt_set_flag(gpt_part_t * p, GPT_ATTR flag, bool value); 145 extern gpt_partitions_t * gpt_read_partitions (gpt_t * gpt); 146 extern int gpt_write_partitions (gpt_partitions_t * parts, gpt_t * header, service_id_t dev_handle); 147 extern gpt_part_t * gpt_alloc_partition (gpt_partitions_t * parts); 148 extern int gpt_add_partition (gpt_partitions_t * parts, gpt_part_t * partition); 149 extern int gpt_remove_partition(gpt_partitions_t * parts, size_t idx); 150 151 extern size_t gpt_get_part_type (gpt_part_t * p); 152 extern void gpt_set_part_type (gpt_part_t * p, size_t type); 153 extern void gpt_set_start_lba (gpt_part_t * p, uint64_t start); 154 extern uint64_t gpt_get_start_lba (gpt_part_t * p); 155 extern void gpt_set_end_lba (gpt_part_t * p, uint64_t start); 156 extern uint64_t gpt_get_end_lba (gpt_part_t * p); 157 extern unsigned char * gpt_get_part_name (gpt_part_t * p); 158 extern void gpt_set_part_name (gpt_part_t * p, char * name[], size_t length); 159 extern bool gpt_get_flag (gpt_part_t * p, GPT_ATTR flag); 160 extern void gpt_set_flag (gpt_part_t * p, GPT_ATTR flag, bool value); 161 162 153 163 154 164 #define gpt_foreach(parts, i, iterator) \ 155 for(size_t i = 0, gpt_part_t * iterator = parts->part_array; 165 for(size_t i = 0, gpt_part_t * iterator = parts->part_array; \ 156 166 i < parts->fill; i++, iterator++) 157 167 -
uspace/lib/mbr/libmbr.c
re91d17a rd617050 48 48 static int decode_logical(mbr_t * mbr, mbr_partitions_t * p, mbr_part_t * ext); 49 49 static void encode_part(mbr_part_t * src, pt_entry_t * trgt, uint32_t base); 50 static int check_overlap(mbr_part_t * p1, mbr_part_t * p2); 51 static int check_encaps(mbr_part_t * inner, mbr_part_t * outer); 52 static int check_preceeds(mbr_part_t * preceeder, mbr_part_t * precedee); 50 53 51 54 /** Read MBR from specific device … … 142 145 if (mbr->raw_data.pte[i].ptype == PT_UNUSED) 143 146 continue; 144 147 145 148 p = malloc(sizeof(mbr_part_t)); 146 149 if (p == NULL) { … … 179 182 int mbr_write_partitions(mbr_partitions_t * parts, mbr_t * mbr, service_id_t dev_handle) 180 183 { 181 bool logical = false;184 //bool logical = false; 182 185 int i = 0; 183 186 int rc; … … 185 188 mbr_part_t * ext = (parts->l_extended == NULL) ? NULL 186 189 : list_get_instance(parts->l_extended, mbr_part_t, link); 187 188 br_block_t * last_ebr = NULL;189 link_t * it;190 190 191 //br_block_t * last_ebr = NULL; 192 //link_t * it; 193 191 194 DEBUG_PRINT_3(LIBMBR_NAME "Writing partitions: n_primary: %u, n_logical:%u, l_extended:%p", parts->n_primary, parts->n_logical, parts->l_extended); 192 195 193 196 rc = block_init(EXCHANGE_ATOMIC, dev_handle, 512); 194 197 if (rc != EOK) { … … 196 199 return rc; 197 200 } 201 /* 202 // Encoding primary partitions 203 for (i = 0; i < parts->n_primary; i++) { 204 encode_part(p, &(mbr->raw_data.pte[i]), 0); 205 } 206 207 // Writing MBR 208 rc = block_write_direct(dev_handle, 0, 1, &(mbr->raw_data)); 209 if (rc != EOK) { 210 DEBUG_PRINT_2(LIBMBR_NAME ": Error (%d): %s.\n", rc, str_error(rc)); 211 goto end; 212 } 213 214 uint32_t base = ext->start_addr; 215 uint32_t addr = base; 216 217 // Encoding and writing logical partitions 218 mbr_part_foreach(parts, p) { 219 if (p->ebr == NULL) { 220 p->ebr = alloc_br(); 221 if (p->ebr == NULL) 222 { 223 rc = ENOMEM; 224 goto end; 225 } 226 } 227 228 229 }*/ 230 231 link_t * l = parts->list.head.next; 232 233 // Encoding primary partitions 234 for (i = 0; i < parts->n_primary; i++) { 235 p = list_get_instance(l, mbr_part_t, link); 236 encode_part(p, &(mbr->raw_data.pte[i]), 0); 237 l = l->next; 238 } 239 240 // Writing MBR 241 rc = block_write_direct(dev_handle, 0, 1, &(mbr->raw_data)); 242 if (rc != EOK) { 243 DEBUG_PRINT_2(LIBMBR_NAME ": Error (%d): %s.\n", rc, str_error(rc)); 244 goto end; 245 } 198 246 199 247 if (ext == NULL) 200 248 goto no_extended; 201 249 250 202 251 uint32_t base = ext->start_addr; 203 252 uint32_t addr = base; 253 254 // Encoding and writing first logical partition 255 if (l != &(parts->list.head)) { 256 p = list_get_instance(l, mbr_part_t, link); 257 if (p->ebr == NULL) { 258 p->ebr = alloc_br(); 259 if (p->ebr == NULL) { 260 rc = ENOMEM; 261 goto end; 262 } 263 } 264 265 encode_part(p, &(p->ebr->pte[0]), base); 266 267 if (l->next == &(parts->list.head)) 268 encode_part(NULL, &(p->ebr->pte[1]), base); 269 else 270 encode_part(list_get_instance(l->next, mbr_part_t, link), &(p->ebr->pte[1]), base); 271 272 273 rc = block_write_direct(dev_handle, base, 1, p->ebr); 274 if (rc != EOK) { 275 DEBUG_PRINT_2(LIBMBR_NAME ": Error (%d): %s.\n", rc, str_error(rc)); 276 goto end; 277 } 278 279 l = l->next; 280 } 281 282 283 284 // Encoding and writing logical partitions 285 while (l != &(parts->list.head)) { 286 p = list_get_instance(l, mbr_part_t, link); 287 if (p->ebr == NULL) { 288 p->ebr = alloc_br(); 289 if (p->ebr == NULL) { 290 rc = ENOMEM; 291 goto end; 292 } 293 } 294 295 addr = p->start_addr - base; 296 encode_part(p, &(p->ebr->pte[0]), addr); 297 298 if (l->next == &(parts->list.head)) 299 encode_part(NULL, &(p->ebr->pte[1]), base); 300 else 301 encode_part(list_get_instance(l->next, mbr_part_t, link), &(p->ebr->pte[1]), base); 302 303 304 rc = block_write_direct(dev_handle, addr, 1, p->ebr); 305 if (rc != EOK) { 306 DEBUG_PRINT_2(LIBMBR_NAME ": Error (%d): %s.\n", rc, str_error(rc)); 307 goto end; 308 } 309 310 l = l->next; 311 } 312 313 no_extended: 314 315 /*if (ext == NULL) 316 goto no_extended; 317 318 uint32_t base = ext->start_addr; 319 uint32_t addr;// = base; 204 320 uint32_t prev_addr; 205 321 mbr_part_t * prev_part = NULL; … … 209 325 if (mbr_get_flag(p, ST_LOGIC)) { 210 326 // writing logical partition 211 212 if (p->start_addr < base || p->start_addr + p->length > base + ext->length) { 213 // out of bounds 214 return EINVAL; 215 } 216 217 327 logical = true; 328 218 329 if (p->ebr == NULL) { 219 330 p->ebr = alloc_br(); … … 225 336 } 226 337 227 228 229 230 338 if (prev_part != NULL) { 231 339 // addr is the address of EBR … … 243 351 addr = base; 244 352 // base-1 means start_lba+1 245 encode_part(p, &(p->ebr->pte[0]), base - 1); 353 // Fixed: mbr_add_partition now performs checks!nevim 354 encode_part(p, &(p->ebr->pte[0]), base); 246 355 } 247 356 248 357 //addr = p->start_addr; 249 358 prev_addr = addr; … … 260 369 ++i; 261 370 } 262 } 371 } //*/ 263 372 264 373 /* If there was an extended but no logical, we should overwrite … … 266 375 * might be some garbage from the past. 267 376 */ 268 377 /* 269 378 last_ebr = prev_part->ebr; 270 379 271 380 if (!logical) 272 381 { … … 276 385 goto end; 277 386 } 278 387 279 388 last_ebr->pte[0].ptype = PT_UNUSED; 280 389 } 281 282 390 391 283 392 encode_part(NULL, &(last_ebr->pte[1]), 0); 284 393 rc = block_write_direct(dev_handle, addr, 1, last_ebr); 285 394 286 395 if (!logical) 287 396 { 288 397 free(last_ebr); 289 398 } 290 399 */ 400 /* 291 401 if (rc != EOK) { 292 402 DEBUG_PRINT_2(LIBMBR_NAME ": Error (%d): %s.\n", rc, str_error(rc)); … … 297 407 298 408 no_extended: 299 409 */ 300 410 /*list_foreach(parts->list, it) { 301 411 p = list_get_instance(it, mbr_part_t, link); … … 313 423 } 314 424 }*/ 315 425 /* 316 426 it = parts->list.head.next; 317 427 for (i = 0; i < N_PRIMARY; i++) { … … 329 439 330 440 } 331 441 332 442 it = it->next; 333 443 } else { … … 335 445 } 336 446 } 337 447 338 448 339 449 skip: … … 343 453 goto end; 344 454 } 455 */ 345 456 346 457 /* … … 405 516 406 517 rc = EOK; 407 518 408 519 end: 409 520 block_fini(dev_handle); … … 437 548 438 549 list_initialize(&(parts->list)); 439 550 440 551 parts->n_primary = 0; 441 552 parts->n_logical = 0; … … 445 556 } 446 557 447 /** Add partition */ 558 /** Add partition 559 * Performs checks, sorts the list. 560 */ 448 561 int mbr_add_partition(mbr_partitions_t * parts, mbr_part_t * p) 449 562 { 450 list_append(&(p->link), &(parts->list));451 563 if (mbr_get_flag(p, ST_LOGIC)) { 564 // adding logical part 565 if (parts->l_extended == NULL) { 566 return ERR_NO_EXTENDED; 567 } 568 if (!check_encaps(p, list_get_instance(parts->l_extended, mbr_part_t, link))) { 569 return ERR_OUT_BOUNDS; 570 } 571 572 mbr_part_t * last = list_get_instance(list_last(&(parts->list)), mbr_part_t, link); 573 mbr_part_foreach(parts, iter) { 574 if (mbr_get_flag(iter, ST_LOGIC)) { 575 if (check_overlap(p, iter)) { 576 return ERR_OVERLAP; 577 } 578 if (check_preceeds(p, iter)) { 579 last = iter; 580 break; 581 } 582 } 583 } 584 585 //list_prepend(&(p->link), &(parts->list)); 586 list_insert_before(&(p->link), &(last->link)); 452 587 parts->n_logical += 1; 453 588 } else { 454 parts->n_primary += 1; 455 } 456 /* if we're adding new logical partition, we need 1 sector for the EBR 457 * for that partition (including the next one); we'd better make sure here 458 * before writing */ 459 if (mbr_get_flag(p, ST_LOGIC) && p->ebr == NULL) { 460 p->start_addr += 1; 461 p->length -= 1; 462 } 463 //FIXME: we can have multiple extended partitions! :-( 464 465 return EOK; 589 // adding primary 590 if (parts->n_primary == 4) { 591 return ERR_PRIMARY_FULL; 592 } 593 if (p->type == PT_EXTENDED && parts->l_extended != NULL) { 594 return ERR_EXTENDED_PRESENT; 595 } 596 597 if (list_empty(&(parts->list))) { 598 list_append(&(p->link), &(parts->list)); 599 } else { 600 mbr_part_foreach(parts, iter) { 601 if (mbr_get_flag(iter, ST_LOGIC)) { 602 list_insert_before(&(p->link), &(iter->link)); 603 parts->n_primary += 1; 604 break; 605 } else if (check_overlap(p, iter)) { 606 return ERR_OVERLAP; 607 } 608 } 609 } 610 } 611 612 return ERR_OK; 466 613 } 467 614 … … 469 616 int mbr_remove_partition(mbr_partitions_t * parts, size_t idx) 470 617 { 471 DEBUG_PRINT_1(LIBMBR_NAME "Removing partition: % d\n", idx);618 DEBUG_PRINT_1(LIBMBR_NAME "Removing partition: %zu\n", idx); 472 619 link_t * l = list_nth(&(parts->list), idx); 473 620 if (l == parts->l_extended) { … … 482 629 parts->n_primary -= 1; 483 630 } 484 485 631 632 486 633 mbr_free_partition(p); 487 634 488 635 return EOK; 489 636 } … … 533 680 mbr_free_partition(p); 534 681 } 535 682 536 683 free(parts); 537 684 } … … 590 737 if (rc != EOK) 591 738 return rc; 592 739 593 740 ebr = alloc_br(); 594 741 if (ebr == NULL) { … … 606 753 goto free_ebr_end; 607 754 } 608 755 609 756 if (ebr->pte[0].ptype == PT_UNUSED) { 610 757 rc = EOK; 611 758 goto free_ebr_end; 612 759 } 613 760 614 761 p = mbr_alloc_partition(); 615 762 if (p == NULL) { … … 617 764 goto free_ebr_end; 618 765 } 619 766 620 767 621 768 decode_part(&(ebr->pte[0]), p, base); … … 625 772 626 773 addr = uint32_t_le2host(ebr->pte[1].first_lba) + base; 627 774 628 775 while (ebr->pte[1].ptype != PT_UNUSED) { 629 776 ebr = alloc_br(); … … 656 803 addr = uint32_t_le2host(ebr->pte[1].first_lba) + base; 657 804 } 658 805 659 806 rc = EOK; 660 807 661 808 free_ebr_end: 662 809 free(ebr); 663 810 664 811 end: 665 812 block_fini(mbr->device); … … 690 837 } 691 838 839 static int check_overlap(mbr_part_t * p1, mbr_part_t * p2) 840 { 841 if (p1->start_addr < p2->start_addr && p1->start_addr + p1->length <= p2->start_addr) { 842 return 0; 843 } else if (p1->start_addr > p2->start_addr && p2->start_addr + p2->length <= p1->start_addr) { 844 return 0; 845 } 846 847 return 1; 848 } 849 850 static int check_encaps(mbr_part_t * inner, mbr_part_t * outer) 851 { 852 if (inner->start_addr <= outer->start_addr || outer->start_addr + outer->length <= inner->start_addr) { 853 return 0; 854 } else if (outer->start_addr + outer->length < inner->start_addr + inner->length) { 855 return 0; 856 } 857 858 return 1; 859 } 860 861 static int check_preceeds(mbr_part_t * preceeder, mbr_part_t * precedee) 862 { 863 return preceeder->start_addr < precedee->start_addr; 864 } 865 866 867 -
uspace/lib/mbr/libmbr.h
re91d17a rd617050 52 52 printf("%s:%d: " str, __FILE__, __LINE__, arg1, arg2, arg3) 53 53 #else 54 #define DEBUG_PRINT_0(str) 54 #define DEBUG_PRINT_0(str) 55 55 #define DEBUG_PRINT_1(str, arg1) 56 56 #define DEBUG_PRINT_2(str, arg1, arg2) … … 87 87 PT_GPT = 0xEE, 88 88 }; 89 90 typedef enum { 91 /** No error */ 92 ERR_OK = 0, 93 /** All primary partitions already present */ 94 ERR_PRIMARY_FULL, 95 /** Extended partition already present */ 96 ERR_EXTENDED_PRESENT, 97 /** No extended partition present */ 98 ERR_NO_EXTENDED, 99 /** Partition overlapping */ 100 ERR_OVERLAP, 101 /** Logical partition out of bounds */ 102 ERR_OUT_BOUNDS, 103 } MBR_ERR_VAL; 104 89 105 90 106 /** Structure of a partition table entry */ … … 146 162 /** Number of primary partitions */ 147 163 unsigned char n_primary; 148 /** Link to the extended partition in the list*/164 /** Index to the extended partition in the array */ 149 165 link_t * l_extended; 150 166 /** Number of logical partitions */ 151 167 unsigned int n_logical; 152 /** Partition linked list */168 /** Logical partition linked list */ 153 169 list_t list; 154 170 } mbr_partitions_t;
Note:
See TracChangeset
for help on using the changeset viewer.