source: mainline/uspace/lib/mbr/libmbr.c@ 9bda5d90

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

libmbr final

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