source: mainline/uspace/lib/mbr/libmbr.c@ 44c4886

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

GPT API changes

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