source: mainline/uspace/lib/mbr/libmbr.c@ c9f61150

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since c9f61150 was a2aa81cb, checked in by Dominik Taborsky (AT DOT) <brembyseznamcz>, 13 years ago

API changes, bug fixing

  • Property mode set to 100644
File size: 20.3 KB
Line 
1/*
2 * Copyright (c) 2011, 2012, 2013 Dominik Taborsky
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The LIBMBR_NAME of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 /** @addtogroup libmbr
30 * @{
31 */
32/** @file MBR extraxtion library
33 */
34
35#include <async.h>
36#include <assert.h>
37#include <block.h>
38#include <byteorder.h>
39#include <errno.h>
40#include <ipc/bd.h>
41#include <mem.h>
42#include <stdio.h>
43#include <stdlib.h>
44
45#include "libmbr.h"
46
47static br_block_t * alloc_br(void);
48static int decode_part(pt_entry_t *, mbr_part_t *, uint32_t);
49static int decode_logical(mbr_label_t *, mbr_part_t *);
50static void encode_part(mbr_part_t *, pt_entry_t *, uint32_t, bool);
51static int check_overlap(mbr_part_t *, mbr_part_t *);
52static int check_encaps(mbr_part_t *, mbr_part_t *);
53static int check_preceeds(mbr_part_t *, mbr_part_t *);
54
55/** Allocate and initialize mbr_label_t structure */
56mbr_label_t * mbr_alloc_label(void)
57{
58 mbr_label_t *label = malloc(sizeof(mbr_label_t));
59 if (label == NULL)
60 return NULL;
61
62 label->mbr = NULL;
63 label->parts = NULL;
64 label->device = 0;
65
66 return label;
67}
68
69/** Free mbr_label_t structure */
70void mbr_free_label(mbr_label_t *label)
71{
72 if (label->mbr != NULL)
73 mbr_free_mbr(label->mbr);
74
75 if (label->parts != NULL)
76 mbr_free_partitions(label->parts);
77
78 free(label);
79}
80
81/** Allocate memory for mbr_t */
82mbr_t * mbr_alloc_mbr(void)
83{
84 return malloc(sizeof(mbr_t));
85}
86
87/** Read MBR from specific device
88 * @param label label to write data to
89 * @param dev_handle device to read MBR from
90 *
91 * @return EOK on success, error code on error
92 */
93int mbr_read_mbr(mbr_label_t *label, service_id_t dev_handle)
94{
95 if (label == NULL)
96 return EINVAL;
97
98 int rc;
99
100 if (label->mbr == NULL) {
101 label->mbr = mbr_alloc_mbr();
102 if (label->mbr == NULL) {
103 return ENOMEM;
104 }
105 }
106
107 rc = block_init(EXCHANGE_ATOMIC, dev_handle, 512);
108 if (rc != EOK)
109 return rc;
110
111 rc = block_read_direct(dev_handle, 0, 1, &(label->mbr->raw_data));
112 block_fini(dev_handle);
113 if (rc != EOK)
114 return rc;
115
116 label->device = dev_handle;
117
118 return EOK;
119}
120
121/** Write mbr to disk
122 * @param label MBR to be written
123 * @param dev_handle device handle to write MBR to (may be different
124 * from the device in 'mbr')
125 *
126 * @return 0 on success, otherwise libblock error code
127 */
128int mbr_write_mbr(mbr_label_t *label, service_id_t dev_handle)
129{
130 int rc;
131
132 rc = block_init(EXCHANGE_ATOMIC, dev_handle, 512);
133 if (rc != EOK) {
134 return rc;
135 }
136
137 rc = block_write_direct(dev_handle, 0, 1, &(label->mbr->raw_data));
138 block_fini(dev_handle);
139 if (rc != EOK) {
140 return rc;
141 }
142
143 return EOK;
144}
145
146/** Decide whether this is an actual MBR or a Protective MBR from GPT
147 *
148 * @param mbr the actual MBR to decide upon
149 *
150 * @return 1 if MBR, 0 if GPT
151 */
152int mbr_is_mbr(mbr_label_t *label)
153{
154 return (label->mbr->raw_data.pte[0].ptype != PT_GPT) ? 1 : 0;
155}
156
157/** Parse partitions from MBR, freeing previous partitions if any
158 * NOTE: it is assumed mbr_read_mbr(label) was called before.
159 * @param label MBR to be parsed
160 *
161 * @return linked list of partitions or NULL on error
162 */
163int mbr_read_partitions(mbr_label_t *label)
164{
165 if (label == NULL || label->mbr == NULL)
166 return EINVAL;
167
168 int rc, rc_ext;
169 unsigned int i;
170 mbr_part_t *p;
171 mbr_part_t *ext = NULL;
172 //mbr_partitions_t *parts;
173 printf("check\n");
174 if (label->parts != NULL)
175 mbr_free_partitions(label->parts);
176 printf("check2\n");
177 label->parts = mbr_alloc_partitions();
178 if (label->parts == NULL) {
179 return ENOMEM;
180 }
181 printf("primary\n");
182 /* Generate the primary partitions */
183 for (i = 0; i < N_PRIMARY; ++i) {
184 if (label->mbr->raw_data.pte[i].ptype == PT_UNUSED)
185 continue;
186 printf("pcheck1\n");
187 p = mbr_alloc_partition();
188 if (p == NULL) {
189 printf(LIBMBR_NAME ": Error on memory allocation.\n");
190 mbr_free_partitions(label->parts);
191 return ENOMEM;
192 }
193 printf("pcheck2\n");
194 rc_ext = decode_part(&(label->mbr->raw_data.pte[i]), p, 0);
195 mbr_set_flag(p, ST_LOGIC, false);
196 rc = mbr_add_partition(label, p);
197 if (rc != ERR_OK) {
198 printf(LIBMBR_NAME ": Error occured during decoding the MBR. (%d)\n" \
199 LIBMBR_NAME ": MBR is invalid.\n", rc);
200 mbr_free_partitions(label->parts);
201 return EINVAL;
202 }
203 printf("pcheck3\n");
204 if (rc_ext) {
205 ext = p;
206 label->parts->l_extended = list_nth(&(label->parts->list), i);
207 }
208 printf("pcheck4\n");
209 }
210 printf("logical\n");
211 /* Fill in the primary partitions and generate logical ones, if any */
212 rc = decode_logical(label, ext);
213 if (rc != EOK) {
214 printf(LIBMBR_NAME ": Error occured during decoding the MBR.\n" \
215 LIBMBR_NAME ": Partition list may be incomplete.\n");
216 return rc;
217 }
218 printf("finish\n");
219 return EOK;
220}
221
222/** Write MBR and partitions to device
223 * @param label label to write
224 * @param dev_handle device to write the data to
225 *
226 * @return returns EOK on succes, specific error code otherwise
227 */
228int mbr_write_partitions(mbr_label_t *label, service_id_t dev_handle)
229{
230 int i = 0;
231 int rc;
232 mbr_part_t *p;
233 mbr_part_t *ext = (label->parts->l_extended == NULL) ? NULL
234 : list_get_instance(label->parts->l_extended, mbr_part_t, link);
235
236 rc = block_init(EXCHANGE_ATOMIC, dev_handle, 512);
237 if (rc != EOK) {
238 printf(LIBMBR_NAME ": Error while initializing libblock: %d - %s.\n", rc, str_error(rc));
239 return rc;
240 }
241
242 link_t *l = label->parts->list.head.next;
243
244 /* Encoding primary partitions */
245 for (i = 0; i < label->parts->n_primary; i++) {
246 p = list_get_instance(l, mbr_part_t, link);
247 encode_part(p, &(label->mbr->raw_data.pte[i]), 0, false);
248 l = l->next;
249 }
250
251 /* Writing MBR */
252 rc = block_write_direct(dev_handle, 0, 1, &(label->mbr->raw_data));
253 if (rc != EOK) {
254 printf(LIBMBR_NAME ": Error while writing MBR : %d - %s.\n", rc, str_error(rc));
255 goto end;
256 }
257
258 if (ext == NULL)
259 goto end;
260
261 uint32_t base = ext->start_addr;
262 mbr_part_t * prev_p;
263
264 /* Note for future changes: Some thought has been put into design
265 * and implementation. If you don't have to change it, don't. Other
266 * designs have been tried, this came out as the least horror with
267 * as much power over it as you can get. Thanks. */
268
269 /* Encoding and writing first logical partition */
270 if (l != &(label->parts->list.head)) {
271 p = list_get_instance(l, mbr_part_t, link);
272 p->ebr_addr = base;
273 encode_part(p, &(p->ebr->pte[0]), base, false);
274 l = l->next;
275 } else {
276 /* If there was an extended but no logical, we should overwrite
277 * the space where the first logical's EBR would have been. There
278 * might be some garbage from the past. */
279 br_block_t * tmp = alloc_br();
280 rc = block_write_direct(dev_handle, base, 1, tmp);
281 if (rc != EOK) {
282 printf(LIBMBR_NAME ": Error while writing EBR: %d - %s.\n", rc, str_error(rc));
283 goto end;
284 }
285 free(tmp);
286 goto end;
287 }
288
289 prev_p = p;
290
291 /* Encoding and writing logical partitions */
292 while (l != &(label->parts->list.head)) {
293 p = list_get_instance(l, mbr_part_t, link);
294
295 /* Checking whether EBR address makes sense. If not, we take a guess.
296 * So far this is simple, we just take the first preceeding sector.
297 * Fdisk always reserves at least 2048 sectors (1MiB), so it can have
298 * the EBR aligned as well as the partition itself. Parted reserves
299 * minimum one sector, like we do.
300 *
301 * Note that we know there is at least one sector free from previous checks.
302 * Also note that the user can set ebr_addr to their liking (if it's valid). */
303 if (p->ebr_addr >= p->start_addr || p->ebr_addr <= (prev_p->start_addr + prev_p->length)) {
304 p->ebr_addr = p->start_addr - 1;
305 DEBUG_PRINT_0(LIBMBR_NAME ": Warning: invalid EBR address.\n");
306 }
307
308 encode_part(p, &(p->ebr->pte[0]), p->ebr_addr, false);
309 encode_part(p, &(prev_p->ebr->pte[1]), base, true);
310
311 rc = block_write_direct(dev_handle, prev_p->ebr_addr, 1, prev_p->ebr);
312 if (rc != EOK) {
313 printf(LIBMBR_NAME ": Error while writing EBR: %d - %s.\n", rc, str_error(rc));
314 goto end;
315 }
316
317 prev_p = p;
318 l = l->next;
319 }
320
321 /* write the last EBR */
322 encode_part(NULL, &(prev_p->ebr->pte[1]), 0, false);
323 rc = block_write_direct(dev_handle, prev_p->ebr_addr, 1, prev_p->ebr);
324 if (rc != EOK) {
325 printf(LIBMBR_NAME ": Error while writing EBR: %d - %s.\n", rc, str_error(rc));
326 goto end;
327 }
328
329 rc = EOK;
330
331end:
332 block_fini(dev_handle);
333
334 return rc;
335}
336
337/** mbr_part_t constructor */
338mbr_part_t * mbr_alloc_partition(void)
339{
340 mbr_part_t *p = malloc(sizeof(mbr_part_t));
341 if (p == NULL) {
342 return NULL;
343 }
344
345 link_initialize(&(p->link));
346 p->ebr = NULL;
347 p->type = PT_UNUSED;
348 p->status = 0;
349 p->start_addr = 0;
350 p->length = 0;
351 p->ebr_addr = 0;
352
353 return p;
354}
355
356/** mbr_partitions_t constructor */
357mbr_partitions_t * mbr_alloc_partitions(void)
358{
359 mbr_partitions_t *parts = malloc(sizeof(mbr_partitions_t));
360 if (parts == NULL) {
361 return NULL;
362 }
363
364 list_initialize(&(parts->list));
365 parts->n_primary = 0;
366 parts->n_logical = 0;
367 parts->l_extended = NULL;
368
369 /* add blank primary partitions */
370 int i;
371 mbr_part_t *p;
372 for (i = 0; i < N_PRIMARY; ++i) {
373 p = mbr_alloc_partition();
374 if (p == NULL) {
375 mbr_free_partitions(parts);
376 return NULL;
377 }
378 list_append(&(p->link), &(parts->list));
379 }
380
381
382 return parts;
383}
384
385/** Add partition
386 * Performs checks, sorts the list.
387 *
388 * @param label label to add to
389 * @param p partition to add
390 *
391 * @return ERR_OK (0) on success, other MBR_ERR_VAL otherwise
392 */
393mbr_err_val mbr_add_partition(mbr_label_t *label, mbr_part_t *p)
394{
395 int rc;
396 mbr_partitions_t *parts = label->parts;
397
398 aoff64_t nblocks;
399 printf("add1.\n");
400 rc = block_init(EXCHANGE_ATOMIC, label->device, 512);
401 if (rc != EOK) {
402 printf(LIBMBR_NAME ": Error while getting number of blocks: %d - %s.\n", rc, str_error(rc));
403 return ERR_LIBBLOCK;
404 }
405 printf("add2.\n");
406 rc = block_get_nblocks(label->device, &nblocks);
407 block_fini(label->device);
408 if (rc != EOK) {
409 printf(LIBMBR_NAME ": Error while getting number of blocks: %d - %s.\n", rc, str_error(rc));
410 return ERR_LIBBLOCK;
411 }
412 printf("add3.\n");
413 if (mbr_get_flag(p, ST_LOGIC)) {
414 /* adding logical partition */
415
416 /* is there any extended partition? */
417 if (parts->l_extended == NULL)
418 return ERR_NO_EXTENDED;
419
420 /* is the logical partition inside the extended one? */
421 mbr_part_t *ext = list_get_instance(parts->l_extended, mbr_part_t, link);
422 if (!check_encaps(p, ext))
423 return ERR_OUT_BOUNDS;
424
425 /* find a place for the new partition in a sorted linked list */
426 //mbr_part_t *last = list_get_instance(list_last(&(parts->list)), mbr_part_t, link);
427 mbr_part_t *iter;
428 //uint32_t ebr_space = 1;
429 mbr_part_foreach(parts, iter) {
430 if (mbr_get_flag(iter, ST_LOGIC)) {
431 if (check_overlap(p, iter))
432 return ERR_OVERLAP;
433 if (check_preceeds(iter, p)) {
434 /* checking if there's at least one sector of space preceeding */
435 if ((iter->start_addr + iter->length) >= p->start_addr - 1)
436 return ERR_NO_EBR;
437 } else {
438 /* checking if there's at least one sector of space following (for following partitions's EBR) */
439 if ((p->start_addr + p->length) >= iter->start_addr - 1)
440 return ERR_NO_EBR;
441 }
442 }
443 }
444
445 /* alloc EBR if it's not already there */
446 if (p->ebr == NULL) {
447 p->ebr = alloc_br();
448 if (p->ebr == NULL) {
449 return ERR_NOMEM;
450 }
451 }
452
453 /* add it */
454 list_append(&(p->link), &(parts->list));
455 parts->n_logical += 1;
456 } else {
457 /* adding primary */
458
459 if (parts->n_primary == 4) {
460 return ERR_PRIMARY_FULL;
461 }
462
463 /* Check if partition makes space for MBR itself. */
464 if (p->start_addr == 0 || ((aoff64_t) p->start_addr) + p->length >= nblocks) {
465 return ERR_OUT_BOUNDS;
466 }
467 printf("add4.\n");
468 /* if it's extended, is there any other one? */
469 if ((p->type == PT_EXTENDED || p->type == PT_EXTENDED_LBA) && parts->l_extended != NULL) {
470 return ERR_EXTENDED_PRESENT;
471 }
472 printf("add5.\n");
473 /* find a place and add it */
474 mbr_part_t *iter;
475 mbr_part_t *empty = NULL;
476 mbr_part_foreach(parts, iter) {
477 printf("type: %x\n", iter->type);
478 if (iter->type == PT_UNUSED) {
479 if (empty == NULL)
480 empty = iter;
481 } else if (check_overlap(p, iter))
482 return ERR_OVERLAP;
483 }
484 printf("add6. %p, %p\n", empty, p);
485 list_insert_after(&(p->link), &(empty->link));
486 printf("add6.1.\n");
487 list_remove(&(empty->link));
488 printf("add6.2.\n");
489 free(empty);
490 printf("add7.\n");
491 parts->n_primary += 1;
492
493 if (p->type == PT_EXTENDED || p->type == PT_EXTENDED_LBA)
494 parts->l_extended = &(p->link);
495 }
496 printf("add8.\n");
497 return ERR_OK;
498}
499
500/** Remove partition
501 * Removes partition by index, indexed from zero. When removing extended
502 * partition, all logical partitions get removed as well.
503 *
504 * @param label label to remove from
505 * @param idx index of the partition to remove
506 *
507 * @return EOK on success, EINVAL if idx invalid
508 */
509int mbr_remove_partition(mbr_label_t *label, size_t idx)
510{
511 link_t *l = list_nth(&(label->parts->list), idx);
512 if (l == NULL)
513 return EINVAL;
514
515 mbr_part_t *p;
516
517 /* If we're removing an extended partition, remove all logical as well */
518 if (l == label->parts->l_extended) {
519 label->parts->l_extended = NULL;
520
521 link_t *it = l->next;
522 link_t *next_it;
523 while (it != &(label->parts->list.head)) {
524 next_it = it->next;
525
526 p = list_get_instance(it, mbr_part_t, link);
527 if (mbr_get_flag(p, ST_LOGIC)) {
528 list_remove(it);
529 label->parts->n_logical -= 1;
530 mbr_free_partition(p);
531 }
532
533 it = next_it;
534 }
535
536 }
537
538 /* Remove the partition itself */
539 p = list_get_instance(l, mbr_part_t, link);
540 if (mbr_get_flag(p, ST_LOGIC)) {
541 label->parts->n_logical -= 1;
542 list_remove(l);
543 mbr_free_partition(p);
544 } else {
545 /* Cannot remove primary - it would break ordering, just zero it */
546 label->parts->n_primary -= 1;
547 p->type = 0;
548 p->status = 0;
549 p->start_addr = 0;
550 p->length = 0;
551 p->ebr_addr = 0;
552 }
553
554 return EOK;
555}
556
557/** mbr_part_t destructor */
558void mbr_free_partition(mbr_part_t *p)
559{
560 if (p->ebr != NULL)
561 free(p->ebr);
562 free(p);
563}
564
565/** Get flag bool value */
566int mbr_get_flag(mbr_part_t *p, MBR_FLAGS flag)
567{
568 return (p->status & (1 << flag)) ? 1 : 0;
569}
570
571/** Set a specifig status flag to a value */
572void mbr_set_flag(mbr_part_t *p, MBR_FLAGS flag, bool value)
573{
574 uint8_t status = p->status;
575
576 if (value)
577 status = status | (1 << flag);
578 else
579 status = status ^ (status & (1 << flag));
580
581 p->status = status;
582}
583
584/** Get next aligned address (in sectors!) */
585uint32_t mbr_get_next_aligned(uint32_t addr, unsigned int alignment)
586{
587 uint32_t div = addr / alignment;
588 return (div + 1) * alignment;
589}
590
591/** Just a wrapper for free() */
592void mbr_free_mbr(mbr_t *mbr)
593{
594 free(mbr);
595}
596
597/** Free partition list
598 *
599 * @param parts partition list to be freed
600 */
601void mbr_free_partitions(mbr_partitions_t *parts)
602{
603 list_foreach_safe(parts->list, cur_link, next) {
604 mbr_part_t *p = list_get_instance(cur_link, mbr_part_t, link);
605 mbr_free_partition(p);
606 }
607
608 free(parts);
609}
610
611// Internal functions follow //
612
613static br_block_t *alloc_br()
614{
615 br_block_t *br = malloc(sizeof(br_block_t));
616 if (br == NULL)
617 return NULL;
618
619 memset(br, 0, 512);
620 br->signature = host2uint16_t_le(BR_SIGNATURE);
621
622 return br;
623}
624
625/** Parse partition entry to mbr_part_t
626 * @return returns 1, if extended partition, 0 otherwise
627 * */
628static int decode_part(pt_entry_t *src, mbr_part_t *trgt, uint32_t base)
629{
630 trgt->type = src->ptype;
631
632 /* Checking only 0x80; otherwise writing will fix to 0x00 */
633 trgt->status = (trgt->status & 0xFF00) | src->status;
634
635 trgt->start_addr = uint32_t_le2host(src->first_lba) + base;
636 trgt->length = uint32_t_le2host(src->length);
637
638 return (src->ptype == PT_EXTENDED) ? 1 : 0;
639}
640
641/** Parse MBR contents to mbr_part_t list */
642static int decode_logical(mbr_label_t *label, mbr_part_t * ext)
643{
644 int rc;
645 mbr_part_t *p;
646
647 if (ext == NULL)
648 return EOK;
649
650 uint32_t base = ext->start_addr;
651 uint32_t addr = base;
652 br_block_t *ebr;
653
654 rc = block_init(EXCHANGE_ATOMIC, label->device, 512);
655 if (rc != EOK)
656 return rc;
657
658 ebr = alloc_br();
659 if (ebr == NULL) {
660 rc = ENOMEM;
661 goto end;
662 }
663
664 rc = block_read_direct(label->device, addr, 1, ebr);
665 if (rc != EOK) {
666 goto free_ebr_end;
667 }
668
669 if (uint16_t_le2host(ebr->signature) != BR_SIGNATURE) {
670 rc = EINVAL;
671 goto free_ebr_end;
672 }
673
674 if (ebr->pte[0].ptype == PT_UNUSED) {
675 rc = EOK;
676 goto free_ebr_end;
677 }
678
679 p = mbr_alloc_partition();
680 if (p == NULL) {
681 rc = ENOMEM;
682 goto free_ebr_end;
683 }
684
685 decode_part(&(ebr->pte[0]), p, base);
686 mbr_set_flag(p, ST_LOGIC, true);
687 p->ebr = ebr;
688 p->ebr_addr = addr;
689 rc = mbr_add_partition(label, p);
690 if (rc != ERR_OK)
691 return EINVAL;
692
693 addr = uint32_t_le2host(ebr->pte[1].first_lba) + base;
694
695 while (ebr->pte[1].ptype != PT_UNUSED) {
696 ebr = alloc_br();
697 if (ebr == NULL) {
698 rc = ENOMEM;
699 goto end;
700 }
701
702 rc = block_read_direct(label->device, addr, 1, ebr);
703 if (rc != EOK) {
704 goto free_ebr_end;
705 }
706
707 if (uint16_t_le2host(ebr->signature) != BR_SIGNATURE) {
708 rc = EINVAL;
709 goto free_ebr_end;
710 }
711
712 p = mbr_alloc_partition();
713 if (p == NULL) {
714 rc = ENOMEM;
715 goto free_ebr_end;
716 }
717
718
719 decode_part(&(ebr->pte[0]), p, addr);
720 mbr_set_flag(p, ST_LOGIC, true);
721 p->ebr = ebr;
722 p->ebr_addr = addr;
723 rc = mbr_add_partition(label, p);
724 if (rc != ERR_OK)
725 return EINVAL;
726
727 addr = uint32_t_le2host(ebr->pte[1].first_lba) + base;
728 }
729
730 rc = EOK;
731 goto end;
732
733free_ebr_end:
734 free(ebr);
735
736end:
737 block_fini(label->device);
738
739 return rc;
740}
741
742/** Convert mbr_part_t to pt_entry_t */
743static void encode_part(mbr_part_t * src, pt_entry_t * trgt, uint32_t base, bool ebr)
744{
745 if (src != NULL) {
746 //trgt->status = mbr_get_flag(src, ST_BOOT) ? B_ACTIVE : B_INACTIVE;
747 trgt->status = (uint8_t) (src->status & 0xFF);
748 /* ingoring CHS */
749 trgt->first_chs[0] = 0xFE;
750 trgt->first_chs[1] = 0xFF;
751 trgt->first_chs[2] = 0xFF;
752 trgt->last_chs[0] = 0xFE;
753 trgt->last_chs[1] = 0xFF;
754 trgt->last_chs[2] = 0xFF;
755 if (ebr) { // encoding reference to EBR
756 trgt->ptype = PT_EXTENDED_LBA;
757 trgt->first_lba = host2uint32_t_le(src->ebr_addr - base);
758 trgt->length = host2uint32_t_le(src->length + src->start_addr - src->ebr_addr);
759 } else { // encoding reference to partition
760 trgt->ptype = src->type;
761 trgt->first_lba = host2uint32_t_le(src->start_addr - base);
762 trgt->length = host2uint32_t_le(src->length);
763 }
764 } else {
765 trgt->status = 0;
766 trgt->first_chs[0] = 0;
767 trgt->first_chs[1] = 0;
768 trgt->first_chs[2] = 0;
769 trgt->ptype = 0;
770 trgt->last_chs[0] = 0;
771 trgt->last_chs[1] = 0;
772 trgt->last_chs[2] = 0;
773 trgt->first_lba = 0;
774 trgt->length = 0;
775 }
776}
777
778/** Check whether two partitions overlap
779 *
780 * @return 1 for yes, 0 for no
781 */
782static int check_overlap(mbr_part_t * p1, mbr_part_t * p2)
783{
784 if (p1->start_addr < p2->start_addr && p1->start_addr + p1->length < p2->start_addr) {
785 return 0;
786 } else if (p1->start_addr > p2->start_addr && p2->start_addr + p2->length < p1->start_addr) {
787 return 0;
788 }
789
790 return 1;
791}
792
793/** Check whether one partition encapsulates the other
794 *
795 * @return 1 for yes, 0 for no
796 */
797static int check_encaps(mbr_part_t * inner, mbr_part_t * outer)
798{
799 if (inner->start_addr <= outer->start_addr || outer->start_addr + outer->length <= inner->start_addr) {
800 return 0;
801 } else if (outer->start_addr + outer->length < inner->start_addr + inner->length) {
802 return 0;
803 }
804
805 return 1;
806}
807
808/** Check whether one partition preceeds the other
809 *
810 * @return 1 for yes, 0 for no
811 */
812static int check_preceeds(mbr_part_t * preceeder, mbr_part_t * precedee)
813{
814 return preceeder->start_addr < precedee->start_addr;
815}
816
817
818
819
Note: See TracBrowser for help on using the repository browser.