Changeset 6453e306 in mainline for uspace/lib


Ignore:
Timestamp:
2013-12-25T16:09:43Z (12 years ago)
Author:
Martin Decky <martin@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
ac36aed
Parents:
d51beba3
Message:

basic code review and coding style cleanup

Location:
uspace/lib
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/gpt/global.c

    rd51beba3 r6453e306  
    11/*
    2  * Copyright (c) 2011, 2012, 2013 Dominik Taborsky
     2 * Copyright (c) 2011-2013 Dominik Taborsky
    33 * All rights reserved.
    44 *
     
    4444};
    4545
    46 const struct partition_type gpt_ptypes[] = {
    47         { "Unused entry",                                       "00000000" "0000" "0000" "0000000000000000" }, /* 0 */
    48         { "HelenOS System",                                     "656C6548" "4F6E" "5320" "53797374656D0000" }, /* 1 It says "HelenOS System\0\0" */
    49         { "MBR partition scheme",                       "024DEE41" "33E7" "11D3" "9D690008C781F39F" },
    50         { "EFI System",                                         "C12A7328" "F81F" "11D2" "BA4B00A0C93EC93B" },
    51         { "BIOS Boot",                                          "21686148" "6449" "6E6F" "744E656564454649" },
    52         { "Windows Reserved",                           "E3C9E316" "0B5C" "4DB8" "817DF92DF00215AE" },
    53         { "Windows Basic data",                         "EBD0A0A2" "B9E5" "4433" "87C068B6B72699C7" },
    54         { "Windows LDM metadata",                       "5808C8AA" "7E8F" "42E0" "85D2E1E90434CFB3" },
    55         { "Windows LDM data",                           "AF9B60A0" "1431" "4F62" "BC683311714A69AD" },
    56         { "Windows Recovery Environment",       "DE94BBA4" "06D1" "4D40" "A16ABFD50179D6AC" },
    57         { "Windows IBM GPFS",                           "37AFFC90" "EF7D" "4E96" "91C32D7AE055B174" }, /* 10 */
    58         { "Windows Cluster metadata",           "DB97DBA9" "0840" "4BAE" "97F0FFB9A327C7E1" },
    59         { "HP-UX Data",                                         "75894C1E" "3AEB" "11D3" "B7C17B03A0000000" },
    60         { "HP-UX Service",                                      "E2A1E728" "32E3" "11D6" "A6827B03A0000000" },
    61         { "Linux filesystem data",                      "0FC63DAF" "8483" "4772" "8E793D69D8477DE4" },
    62         { "Linux RAID",                                         "A19D880F" "05FC" "4D3B" "A006743F0F84911E" },
    63         { "Linux Swap",                                         "0657FD6D" "A4AB" "43C4" "84E50933C84B4F4F" },
    64         { "Linux LVM",                                          "E6D6D379" "F507" "44C2" "A23C238F2A3DF928" },
    65         { "Linux filesystem data",                      "933AC7E1" "2EB4" "4F13" "B8440E14E2AEF915" },
    66         { "Linux Reserved",                                     "8DA63339" "0007" "60C0" "C436083AC8230908" },
    67         { "FreeBSD Boot",                                       "83BD6B9D" "7F41" "11DC" "BE0B001560B84F0F" }, /* 20 */
    68         { "FreeBSD Data",                                       "516E7CB4" "6ECF" "11D6" "8FF800022D09712B" },
    69         { "FreeBSD Swap",                                       "516E7CB5" "6ECF" "11D6" "8FF800022D09712B" },
    70         { "FreeBSD UFS",                                        "516E7CB6" "6ECF" "11D6" "8FF800022D09712B" },
    71         { "FreeBSD Vinum VM",                           "516E7CB8" "6ECF" "11D6" "8FF800022D09712B" },
    72         { "FreeBSD ZFS",                                        "516E7CBA" "6ECF" "11D6" "8FF800022D09712B" },
    73         { "Mac OS X HFS+",                                      "48465300" "0000" "11AA" "AA1100306543ECAC" },
    74         { "Mac OS X UFS",                                       "55465300" "0000" "11AA" "AA1100306543ECAC" },
    75         { "Mac OS X ZFS",                                       "6A898CC3" "1DD2" "11B2" "99A6080020736631" },
    76         { "Mac OS X RAID",                                      "52414944" "0000" "11AA" "AA1100306543ECAC" },
    77         { "Mac OS X RAID, offline",                     "52414944" "5F4F" "11AA" "AA1100306543ECAC" }, /* 30 */
    78         { "Mac OS X Boot",                                      "426F6F74" "0000" "11AA" "AA1100306543ECAC" },
    79         { "Mac OS X Label",                                     "4C616265" "6C00" "11AA" "AA1100306543ECAC" },
    80         { "Mac OS X TV Recovery",                       "5265636F" "7665" "11AA" "AA1100306543ECAC" },
    81         { "Mac OS X Core Storage",                      "53746F72" "6167" "11AA" "AA1100306543ECAC" },
    82         { "Solaris Boot",                                       "6A82CB45" "1DD2" "11B2" "99A6080020736631" },
    83         { "Solaris Root",                                       "6A85CF4D" "1DD2" "11B2" "99A6080020736631" },
    84         { "Solaris Swap",                                       "6A87C46F" "1DD2" "11B2" "99A6080020736631" },
    85         { "Solaris Backup",                                     "6A8B642B" "1DD2" "11B2" "99A6080020736631" },
    86         { "Solaris /usr",                                       "6A898CC3" "1DD2" "11B2" "99A6080020736631" },
    87         { "Solaris /var",                                       "6A8EF2E9" "1DD2" "11B2" "99A6080020736631" }, /* 40 */
    88         { "Solaris /home",                                      "6A90BA39" "1DD2" "11B2" "99A6080020736631" },
    89         { "Solaris Alternate sector",           "6A9283A5" "1DD2" "11B2" "99A6080020736631" },
    90         { "Solaris Reserved",                           "6A945A3B" "1DD2" "11B2" "99A6080020736631" },
    91         { "Solaris Reserved",                           "6A9630D1" "1DD2" "11B2" "99A6080020736631" },
    92         { "Solaris Reserved",                           "6A980767" "1DD2" "11B2" "99A6080020736631" },
    93         { "Solaris Reserved",                           "6A96237F" "1DD2" "11B2" "99A6080020736631" },
    94         { "Solaris Reserved",                           "6A8D2AC7" "1DD2" "11B2" "99A6080020736631" },
    95         { "NetBSD Swap",                                        "49F48D32" "B10E" "11DC" "B99B0019D1879648" },
    96         { "NetBSD FFS",                                         "49F48D5A" "B10E" "11DC" "B99B0019D1879648" },
    97         { "NetBSD LFS",                                         "49F48D82" "B10E" "11DC" "B99B0019D1879648" }, /* 50 */
    98         { "NetBSD RAID",                                        "49F48DAA" "B10E" "11DC" "B99B0019D1879648" },
    99         { "NetBSD Concatenated",                        "2DB519C4" "B10F" "11DC" "B99B0019D1879648" },
    100         { "NetBSD Encrypted",                           "2DB519EC" "B10F" "11DC" "B99B0019D1879648" },
    101         { "ChromeOS ChromeOS kernel",           "FE3A2A5D" "4F32" "41A7" "B725ACCC3285A309" },
    102         { "ChromeOS rootfs",                            "3CB8E202" "3B7E" "47DD" "8A3C7FF2A13CFCEC" },
    103         { "ChromeOS future use",                        "2E0A753D" "9E48" "43B0" "8337B15192CB1B5E" },
    104         { "MidnightBSD Boot",                           "85D5E45E" "237C" "11E1" "B4B3E89A8F7FC3A7" },
    105         { "MidnightBSD Data",                           "85D5E45A" "237C" "11E1" "B4B3E89A8F7FC3A7" },
    106         { "MidnightBSD Swap",                           "85D5E45B" "237C" "11E1" "B4B3E89A8F7FC3A7" },
    107         { "MidnightBSD UFS",                            "0394Ef8B" "237E" "11E1" "B4B3E89A8F7FC3A7" }, /* 60 */
    108         { "MidnightBSD Vinum VM",                       "85D5E45C" "237C" "11E1" "B4B3E89A8F7FC3A7" },
    109         { "MidnightBSD ZFS",                            "85D5E45D" "237C" "11E1" "B4B3E89A8F7FC3A7" },
    110         { "Uknown", NULL} /* keep this as the last one! gpt_get_part_type depends on it! */
     46const partition_type_t gpt_ptypes[] = {
     47        { "unused entry",                 "00000000" "0000" "0000" "0000000000000000" }, /* 0 */
     48        { "HelenOS System",               "3dc61fa0" "cf7a" "3ad8" "ac57615029d81a6b" }, /* "HelenOS System" encoded as RFC 4122 UUID, version 3 (MD5 name-based) */
     49        { "MBR partition scheme",         "024dee41" "33e7" "11d3" "9d690008c781f39f" },
     50        { "EFI System",                   "c12a7328" "f81f" "11d2" "ba4b00a0c93ec93b" },
     51        { "BIOS Boot",                    "21686148" "6449" "6e6f" "744e656564454649" },
     52        { "Windows Reserved",             "e3c9e316" "0b5c" "4db8" "817df92df00215ae" },
     53        { "Windows Basic data",           "ebd0a0a2" "b9e5" "4433" "87c068b6b72699c7" },
     54        { "Windows LDM metadata",         "5808c8aa" "7e8f" "42e0" "85d2e1e90434cfb3" },
     55        { "Windows LDM data",             "af9b60a0" "1431" "4f62" "bc683311714a69ad" },
     56        { "Windows Recovery Environment", "de94bba4" "06d1" "4d40" "a16abfd50179d6ac" },
     57        { "Windows IBM GPFS",             "37affc90" "ef7d" "4e96" "91c32d7ae055b174" }, /* 10 */
     58        { "Windows Cluster metadata",     "db97dba9" "0840" "4bae" "97f0ffb9a327c7e1" },
     59        { "HP-UX Data",                   "75894c1e" "3aeb" "11d3" "b7c17b03a0000000" },
     60        { "HP-UX Service",                "e2a1e728" "32e3" "11d6" "a6827b03a0000000" },
     61        { "Linux filesystem data",        "0fc63daf" "8483" "4772" "8e793d69d8477de4" },
     62        { "Linux RAID",                   "a19d880f" "05fc" "4d3b" "a006743f0f84911e" },
     63        { "Linux Swap",                   "0657fd6d" "a4ab" "43c4" "84e50933c84b4f4f" },
     64        { "Linux LVM",                    "e6d6d379" "f507" "44c2" "a23c238f2a3df928" },
     65        { "Linux filesystem data",        "933ac7e1" "2eb4" "4f13" "b8440e14e2aef915" },
     66        { "Linux Reserved",               "8da63339" "0007" "60c0" "c436083ac8230908" },
     67        { "FreeBSD Boot",                 "83bd6b9d" "7f41" "11dc" "be0b001560b84f0f" }, /* 20 */
     68        { "FreeBSD Data",                 "516e7cb4" "6ecf" "11d6" "8ff800022d09712b" },
     69        { "FreeBSD Swap",                 "516e7cb5" "6ecf" "11d6" "8ff800022d09712b" },
     70        { "FreeBSD UFS",                  "516e7cb6" "6ecf" "11d6" "8ff800022d09712b" },
     71        { "FreeBSD Vinum VM",             "516e7cb8" "6ecf" "11d6" "8ff800022d09712b" },
     72        { "FreeBSD ZFS",                  "516e7cba" "6ecf" "11d6" "8ff800022d09712b" },
     73        { "Mac OS X HFS+",                "48465300" "0000" "11aa" "aa1100306543ecac" },
     74        { "Mac OS X UFS",                 "55465300" "0000" "11aa" "aa1100306543ecac" },
     75        { "Mac OS X ZFS",                 "6a898cc3" "1dd2" "11b2" "99a6080020736631" },
     76        { "Mac OS X RAID",                "52414944" "0000" "11aa" "aa1100306543ecac" },
     77        { "Mac OS X RAID, offline",       "52414944" "5f4f" "11aa" "aa1100306543ecac" }, /* 30 */
     78        { "Mac OS X Boot",                "426f6f74" "0000" "11aa" "aa1100306543ecac" },
     79        { "Mac OS X Label",               "4c616265" "6c00" "11aa" "aa1100306543ecac" },
     80        { "Mac OS X TV Recovery",         "5265636f" "7665" "11aa" "aa1100306543ecac" },
     81        { "Mac OS X Core Storage",        "53746f72" "6167" "11aa" "aa1100306543ecac" },
     82        { "Solaris Boot",                 "6a82cb45" "1dd2" "11b2" "99a6080020736631" },
     83        { "Solaris Root",                 "6a85cf4d" "1dd2" "11b2" "99a6080020736631" },
     84        { "Solaris Swap",                 "6a87c46f" "1dd2" "11b2" "99a6080020736631" },
     85        { "Solaris Backup",               "6a8b642b" "1dd2" "11b2" "99a6080020736631" },
     86        { "Solaris /usr",                 "6a898cc3" "1dd2" "11b2" "99a6080020736631" },
     87        { "Solaris /var",                 "6a8ef2e9" "1dd2" "11b2" "99a6080020736631" }, /* 40 */
     88        { "Solaris /home",                "6a90ba39" "1dd2" "11b2" "99a6080020736631" },
     89        { "Solaris Alternate sector",     "6a9283a5" "1dd2" "11b2" "99a6080020736631" },
     90        { "Solaris Reserved",             "6a945a3b" "1dd2" "11b2" "99a6080020736631" },
     91        { "Solaris Reserved",             "6a9630d1" "1dd2" "11b2" "99a6080020736631" },
     92        { "Solaris Reserved",             "6a980767" "1dd2" "11b2" "99a6080020736631" },
     93        { "Solaris Reserved",             "6a96237f" "1dd2" "11b2" "99a6080020736631" },
     94        { "Solaris Reserved",             "6a8d2ac7" "1dd2" "11b2" "99a6080020736631" },
     95        { "NetBSD Swap",                  "49f48d32" "b10e" "11dc" "b99b0019d1879648" },
     96        { "NetBSD FFS",                   "49f48d5a" "b10e" "11dc" "b99b0019d1879648" },
     97        { "NetBSD LFS",                   "49f48d82" "b10e" "11dc" "b99b0019d1879648" }, /* 50 */
     98        { "NetBSD RAID",                  "49f48daa" "b10e" "11dc" "b99b0019d1879648" },
     99        { "NetBSD Concatenated",          "2db519c4" "b10f" "11dc" "b99b0019d1879648" },
     100        { "NetBSD Encrypted",             "2db519ec" "b10f" "11dc" "b99b0019d1879648" },
     101        { "ChromeOS ChromeOS kernel",     "fe3a2a5d" "4f32" "41a7" "b725accc3285a309" },
     102        { "ChromeOS rootfs",              "3cb8e202" "3b7e" "47dd" "8a3c7ff2a13cfcec" },
     103        { "ChromeOS future use",          "2e0a753d" "9e48" "43b0" "8337b15192cb1b5e" },
     104        { "MidnightBSD Boot",             "85d5e45e" "237c" "11e1" "b4b3e89a8f7fc3a7" },
     105        { "MidnightBSD Data",             "85d5e45a" "237c" "11e1" "b4b3e89a8f7fc3a7" },
     106        { "MidnightBSD Swap",             "85d5e45b" "237c" "11e1" "b4b3e89a8f7fc3a7" },
     107        { "MidnightBSD UFS",              "0394ef8b" "237e" "11e1" "b4b3e89a8f7fc3a7" }, /* 60 */
     108        { "MidnightBSD Vinum VM",         "85d5e45c" "237c" "11e1" "b4b3e89a8f7fc3a7" },
     109        { "MidnightBSD ZFS",              "85d5e45d" "237c" "11e1" "b4b3e89a8f7fc3a7" },
     110        { "unknown entry",                NULL } /* Keep this as the last entry */
    111111};
    112 
    113 
    114 
  • uspace/lib/gpt/gpt.h

    rd51beba3 r6453e306  
    11/*
    22 * Copyright (c) 2009 Jiri Svoboda
    3  * Copyright (c) 2011, 2012, 2013 Dominik Taborsky
     3 * Copyright (c) 2011-2013 Dominik Taborsky
    44 * All rights reserved.
    55 *
     
    4343        AT_UNDEFINED,
    4444        AT_SPECIFIC = 48
    45 } GPT_ATTR;
     45} gpt_attr_t;
    4646
    47 /** GPT header
    48  * - all in little endian.
    49  */
     47/** GPT header */
    5048typedef struct {
    51         uint8_t  efi_signature[8];
    52         uint8_t  revision[4];
     49        uint8_t efi_signature[8];
     50        uint8_t revision[4];
    5351        uint32_t header_size;
    5452        uint32_t header_crc32;
    5553        uint32_t reserved;
    56         uint64_t my_lba;
     54        uint64_t current_lba;
    5755        uint64_t alternate_lba;
    5856        uint64_t first_usable_lba;
    5957        uint64_t last_usable_lba;
    60         uint8_t  disk_guid[16];
     58        uint8_t disk_guid[16];
    6159        uint64_t entry_lba;
    6260        uint32_t fillries;
     
    7674
    7775#endif
    78 
    79 
  • uspace/lib/gpt/libgpt.c

    rd51beba3 r6453e306  
    11/*
    2  * Copyright (c) 2011, 2012, 2013 Dominik Taborsky
     2 * Copyright (c) 2011-2013 Dominik Taborsky
    33 * All rights reserved.
    44 *
     
    3434
    3535/* TODO:
    36  * This implementation only supports fixed size partition entries. Specification
    37  * requires otherwise, though. Use void * array and casting to achieve that.
     36 * The implementation currently supports fixed size partition entries only.
     37 * The specification requires otherwise, though.
    3838 */
    3939
     
    4646#include <assert.h>
    4747#include <byteorder.h>
    48 #include <checksum.h>
     48#include <adt/checksum.h>
    4949#include <mem.h>
    5050#include <sys/typefmt.h>
    5151#include <mbr.h>
    52 
    53 
     52#include <align.h>
    5453#include "libgpt.h"
    5554
    5655static int load_and_check_header(service_id_t, aoff64_t, size_t, gpt_header_t *);
    57 static gpt_partitions_t * alloc_part_array(uint32_t);
     56static gpt_partitions_t *alloc_part_array(uint32_t);
    5857static int extend_part_array(gpt_partitions_t *);
    5958static int reduce_part_array(gpt_partitions_t *);
     
    6261static bool check_encaps(gpt_part_t *, uint64_t, uint64_t);
    6362
    64 /** Allocate memory for gpt label */
    65 gpt_label_t * gpt_alloc_label(void)
     63/** Allocate a GPT label */
     64gpt_label_t *gpt_alloc_label(void)
    6665{
    6766        gpt_label_t *label = malloc(sizeof(gpt_label_t));
     
    6968                return NULL;
    7069       
    71         /* This is necessary so that gpt_part_foreach does not segfault */
    7270        label->parts = gpt_alloc_partitions();
    73         if (label == NULL) {
     71        if (label->parts == NULL) {
    7472                free(label);
    7573                return NULL;
     
    7775       
    7876        label->gpt = NULL;
    79        
    8077        label->device = 0;
    8178       
     
    8380}
    8481
    85 /** Free gpt_label_t structure */
     82/** Free a GPT label */
    8683void gpt_free_label(gpt_label_t *label)
    8784{
     
    9592}
    9693
    97 /** Allocate memory for gpt header */
    98 gpt_t * gpt_alloc_header(size_t size)
     94/** Allocate a GPT header */
     95gpt_t *gpt_alloc_header(size_t size)
    9996{
    10097        gpt_t *gpt = malloc(sizeof(gpt_t));
     
    10299                return NULL;
    103100       
    104         /* 
    105          * We might need only sizeof(gpt_header_t), but we should follow 
     101        /*
     102         * We might need only sizeof(gpt_header_t), but we should follow
    106103         * specs and have zeroes through all the rest of the block
    107104         */
    108         size_t final_size = size > sizeof(gpt_header_t) ? size : sizeof(gpt_header_t);
     105        size_t final_size = max(size, sizeof(gpt_header_t));
    109106        gpt->header = malloc(final_size);
    110107        if (gpt->header == NULL) {
     
    113110        }
    114111       
    115         /* Enter some sane defaults. */
    116112        memset(gpt->header, 0, final_size);
    117113        memcpy(gpt->header->efi_signature, efi_signature, 8);
     
    121117        gpt->header->entry_size = host2uint32_t_le(sizeof(gpt_entry_t));
    122118       
    123        
    124119        return gpt;
    125120}
    126121
    127 /** free() GPT header including gpt->header_lba */
     122/** Free a GPT header */
    128123void gpt_free_gpt(gpt_t *gpt)
    129124{
     
    132127}
    133128
    134 /** Read GPT from specific device
    135  * @param label        label structure to fill
    136  * @param dev_handle   device to read GPT from
    137  *
    138  * @return             EOK on success, errorcode on error
     129/** Read GPT from a device
     130 *
     131 * @param label      Label to read.
     132 * @param dev_handle Device to read GPT from.
     133 *
     134 * @return EOK on success, error code on error.
     135 *
    139136 */
    140137int gpt_read_header(gpt_label_t *label, service_id_t dev_handle)
    141138{
    142         int rc;
    143         size_t b_size;
    144        
    145         rc = block_init(EXCHANGE_ATOMIC, dev_handle, 512);
    146         if (rc != EOK)
    147                 goto fail;
    148        
    149         rc = block_get_bsize(dev_handle, &b_size);
    150         if (rc != EOK)
    151                 goto fini_fail;
     139        int rc = block_init(EXCHANGE_ATOMIC, dev_handle, 512);
     140        if (rc != EOK)
     141                return rc;
     142       
     143        size_t block_size;
     144        rc = block_get_bsize(dev_handle, &block_size);
     145        if (rc != EOK)
     146                goto end;
    152147       
    153148        if (label->gpt == NULL) {
    154                 label->gpt = gpt_alloc_header(b_size);
     149                label->gpt = gpt_alloc_header(block_size);
    155150                if (label->gpt == NULL) {
    156151                        rc = ENOMEM;
    157                         goto fini_fail;
     152                        goto end;
    158153                }
    159154        }
    160155       
    161         rc = load_and_check_header(dev_handle, GPT_HDR_BA, b_size, label->gpt->header);
    162         if (rc == EBADCHECKSUM || rc == EINVAL) {
    163                 aoff64_t n_blocks;
    164                 rc = block_get_nblocks(dev_handle, &n_blocks);
    165                 if (rc != EOK)
    166                         goto free_fail;
    167 
    168                 rc = load_and_check_header(dev_handle, n_blocks - 1, b_size, label->gpt->header);
    169                 if (rc == EBADCHECKSUM || rc == EINVAL)
    170                         goto free_fail;
     156        rc = load_and_check_header(dev_handle, GPT_HDR_BA, block_size,
     157            label->gpt->header);
     158        if ((rc == EBADCHECKSUM) || (rc == EINVAL)) {
     159                aoff64_t blocks;
     160                rc = block_get_nblocks(dev_handle, &blocks);
     161                if (rc != EOK) {
     162                        gpt_free_gpt(label->gpt);
     163                        goto end;
     164                }
     165               
     166                rc = load_and_check_header(dev_handle, blocks - 1, block_size,
     167                    label->gpt->header);
     168                if ((rc == EBADCHECKSUM) || (rc == EINVAL)) {
     169                        gpt_free_gpt(label->gpt);
     170                        goto end;
     171                }
    171172        }
    172173       
    173174        label->device = dev_handle;
     175        rc = EOK;
     176       
     177end:
    174178        block_fini(dev_handle);
    175         return EOK;
    176        
    177 free_fail:
    178         gpt_free_gpt(label->gpt);
    179         label->gpt = NULL;
    180 fini_fail:
    181         block_fini(dev_handle);
    182 fail:
    183179        return rc;
    184180}
    185181
    186182/** Write GPT header to device
    187  * @param label        GPT label header to be written
    188  * @param dev_handle   device handle to write the data to
    189  *
    190  * @return             EOK on success, libblock error code otherwise
    191  *
    192  * Note: Firstly write partitions (if modified), then gpt header.
     183 *
     184 * @param label        Label to be written.
     185 * @param dev_handle   Device to write the GPT to.
     186 *
     187 * @return EOK on success, libblock error code otherwise.
     188 *
    193189 */
    194190int gpt_write_header(gpt_label_t *label, service_id_t dev_handle)
    195191{
    196         int rc;
    197         size_t b_size;
    198        
    199192        /* The comm_size argument (the last one) is ignored */
    200         rc = block_init(EXCHANGE_ATOMIC, dev_handle, 4096);
    201         if (rc != EOK && rc != EEXIST)
     193        int rc = block_init(EXCHANGE_ATOMIC, dev_handle, 4096);
     194        if ((rc != EOK) && (rc != EEXIST))
    202195                return rc;
    203196       
    204         rc = block_get_bsize(dev_handle, &b_size);
    205         if (rc != EOK)
    206                 return rc;
    207        
    208         aoff64_t n_blocks;
    209         rc = block_get_nblocks(dev_handle, &n_blocks);
    210         if (rc != EOK) {
    211                 block_fini(dev_handle);
    212                 return rc;
    213         }
    214        
    215         uint64_t tmp;
     197        size_t block_size;
     198        rc = block_get_bsize(dev_handle, &block_size);
     199        if (rc != EOK)
     200                goto end;
     201       
     202        aoff64_t blocks;
     203        rc = block_get_nblocks(dev_handle, &blocks);
     204        if (rc != EOK)
     205                goto end;
    216206       
    217207        gpt_set_random_uuid(label->gpt->header->disk_guid);
    218208       
    219209        /* Prepare the backup header */
    220         label->gpt->header->alternate_lba = label->gpt->header->my_lba;
    221         label->gpt->header->my_lba = host2uint64_t_le(n_blocks - 1);
    222        
    223         tmp = label->gpt->header->entry_lba;
    224         label->gpt->header->entry_lba = host2uint64_t_le(n_blocks -
    225             (uint32_t_le2host(label->gpt->header->fillries) * sizeof(gpt_entry_t))
    226             / b_size - 1);
     210        label->gpt->header->alternate_lba = label->gpt->header->current_lba;
     211        label->gpt->header->current_lba = host2uint64_t_le(blocks - 1);
     212       
     213        uint64_t lba = label->gpt->header->entry_lba;
     214        label->gpt->header->entry_lba = host2uint64_t_le(blocks -
     215            (uint32_t_le2host(label->gpt->header->fillries) *
     216            sizeof(gpt_entry_t)) / block_size - 1);
    227217       
    228218        label->gpt->header->header_crc32 = 0;
    229         label->gpt->header->header_crc32 = host2uint32_t_le(
    230             compute_crc32((uint8_t *) label->gpt->header,
    231                 uint32_t_le2host(label->gpt->header->header_size)));
     219        label->gpt->header->header_crc32 =
     220            host2uint32_t_le(compute_crc32((uint8_t *) label->gpt->header,
     221            uint32_t_le2host(label->gpt->header->header_size)));
    232222       
    233223        /* Write to backup GPT header location */
    234         rc = block_write_direct(dev_handle, n_blocks - 1, GPT_HDR_BS, label->gpt->header);
    235         if (rc != EOK) {
    236                 block_fini(dev_handle);
    237                 return rc;
    238         }
    239        
     224        rc = block_write_direct(dev_handle, blocks - 1, GPT_HDR_BS,
     225            label->gpt->header);
     226        if (rc != EOK)
     227                goto end;
    240228       
    241229        /* Prepare the main header */
    242         label->gpt->header->entry_lba = tmp;
    243        
    244         tmp = label->gpt->header->alternate_lba;
    245         label->gpt->header->alternate_lba = label->gpt->header->my_lba;
    246         label->gpt->header->my_lba = tmp;
     230        label->gpt->header->entry_lba = lba;
     231       
     232        lba = label->gpt->header->alternate_lba;
     233        label->gpt->header->alternate_lba = label->gpt->header->current_lba;
     234        label->gpt->header->current_lba = lba;
    247235       
    248236        label->gpt->header->header_crc32 = 0;
    249         label->gpt->header->header_crc32 = host2uint32_t_le(
    250             compute_crc32((uint8_t *) label->gpt->header,
    251                 uint32_t_le2host(label->gpt->header->header_size)));
     237        label->gpt->header->header_crc32 =
     238            host2uint32_t_le(compute_crc32((uint8_t *) label->gpt->header,
     239            uint32_t_le2host(label->gpt->header->header_size)));
    252240       
    253241        /* Write to main GPT header location */
    254         rc = block_write_direct(dev_handle, GPT_HDR_BA, GPT_HDR_BS, label->gpt->header);
    255         if (rc != EOK)
    256                 return rc;
     242        rc = block_write_direct(dev_handle, GPT_HDR_BA, GPT_HDR_BS,
     243            label->gpt->header);
     244        if (rc != EOK)
     245                goto end;
    257246       
    258247        /* Write Protective MBR */
    259248        br_block_t mbr;
    260249        memset(&mbr, 0, 512);
     250       
    261251        memset(mbr.pte[0].first_chs, 1, 3);
    262252        mbr.pte[0].ptype = 0xEE;
    263         memset(mbr.pte[0].last_chs, 0xFF, 3);
     253        memset(mbr.pte[0].last_chs, 0xff, 3);
    264254        mbr.pte[0].first_lba = host2uint32_t_le(1);
    265         mbr.pte[0].length = 0xFFFFFFFF;
     255        mbr.pte[0].length = 0xffffffff;
    266256        mbr.signature = host2uint16_t_le(BR_SIGNATURE);
    267257       
    268258        rc = block_write_direct(dev_handle, 0, 1, &mbr);
     259       
     260end:
    269261        block_fini(dev_handle);
    270         if (rc != EOK)
    271                 return rc;
    272        
    273         return 0;
     262        return rc;
    274263}
    275264
    276265/** Alloc partition array */
    277 gpt_partitions_t * gpt_alloc_partitions()
     266gpt_partitions_t *gpt_alloc_partitions(void)
    278267{
    279268        return alloc_part_array(GPT_MIN_PART_NUM);
     
    281270
    282271/** Parse partitions from GPT
    283  * @param label   GPT label to be parsed
    284  *
    285  * @return        EOK on success, errorcode otherwise
     272 *
     273 * @param label GPT label to be parsed.
     274 *
     275 * @return EOK on success, error code otherwise.
     276 *
    286277 */
    287278int gpt_read_partitions(gpt_label_t *label)
    288279{
    289         int rc;
    290         unsigned int i;
    291280        uint32_t fillries = uint32_t_le2host(label->gpt->header->fillries);
    292281        uint32_t ent_size = uint32_t_le2host(label->gpt->header->entry_size);
     
    295284        if (label->parts == NULL) {
    296285                label->parts = alloc_part_array(fillries);
    297                 if (label->parts == NULL) {
     286                if (label->parts == NULL)
    298287                        return ENOMEM;
    299                 }
    300         }
    301 
    302         /* comm_size is ignored */
    303         rc = block_init(EXCHANGE_SERIALIZE, label->device, sizeof(gpt_entry_t));
    304         if (rc != EOK)
    305                 goto fail;
    306 
     288        }
     289       
     290        int rc = block_init(EXCHANGE_SERIALIZE, label->device,
     291            sizeof(gpt_entry_t));
     292        if (rc != EOK) {
     293                gpt_free_partitions(label->parts);
     294                label->parts = NULL;
     295                goto end;
     296        }
     297       
    307298        size_t block_size;
    308299        rc = block_get_bsize(label->device, &block_size);
    309         if (rc != EOK)
    310                 goto fini_fail;
    311 
     300        if (rc != EOK) {
     301                gpt_free_partitions(label->parts);
     302                label->parts = NULL;
     303                goto end;
     304        }
     305       
    312306        aoff64_t pos = ent_lba * block_size;
    313 
    314         /*
    315          * Now we read just sizeof(gpt_entry_t) bytes for each entry from the device.
    316          * Hopefully, this does not bypass cache (no mention in libblock.c),
    317          * and also allows us to have variable partition entry size (but we
    318          * will always read just sizeof(gpt_entry_t) bytes - hopefully they
    319          * don't break backward compatibility)
    320          */
    321         for (i = 0; i < fillries; ++i) {
    322                 /*FIXME: this does bypass cache... */
    323                 rc = block_read_bytes_direct(label->device, pos, sizeof(gpt_entry_t), label->parts->part_array + i);
    324                 /*
    325                  * FIXME: but seqread() is just too complex...
    326                  * rc = block_seqread(gpt->device, &bufpos, &buflen, &pos, res->part_array[i], sizeof(gpt_entry_t));
    327                  */
     307       
     308        for (uint32_t i = 0; i < fillries; i++) {
     309                rc = block_read_bytes_direct(label->device, pos, sizeof(gpt_entry_t),
     310                    label->parts->part_array + i);
    328311                pos += ent_size;
    329 
    330                 if (rc != EOK)
    331                         goto fini_fail;
    332         }
    333        
    334         uint32_t crc = compute_crc32((uint8_t *) label->parts->part_array,
    335                            fillries * ent_size);
    336 
    337         if (uint32_t_le2host(label->gpt->header->pe_array_crc32) != crc)
    338         {
     312               
     313                if (rc != EOK) {
     314                        gpt_free_partitions(label->parts);
     315                        label->parts = NULL;
     316                        goto end;
     317                }
     318        }
     319       
     320        uint32_t crc = compute_crc32((uint8_t *) label->parts->part_array,
     321            fillries * ent_size);
     322       
     323        if (uint32_t_le2host(label->gpt->header->pe_array_crc32) != crc) {
    339324                rc = EBADCHECKSUM;
    340                 goto fini_fail;
    341         }
    342        
     325                gpt_free_partitions(label->parts);
     326                label->parts = NULL;
     327                goto end;
     328        }
     329       
     330        rc = EOK;
     331       
     332end:
    343333        block_fini(label->device);
    344         return EOK;
    345        
    346 fini_fail:
    347         block_fini(label->device);
    348        
    349 fail:
    350         gpt_free_partitions(label->parts);
    351         label->parts = NULL;
    352334        return rc;
    353335}
    354336
    355337/** Write GPT and partitions to device
    356  * Note: also writes the header.
    357  * @param label        label to write
    358  * @param dev_handle   device to write the data to
    359  *
    360  * @return             returns EOK on succes, errorcode otherwise
     338 *
     339 * Note: Also writes the header.
     340 *
     341 * @param label      Label to write.
     342 * @param dev_handle Device to write the data to.
     343 *
     344 * @return EOK on succes, error code otherwise
     345 *
    361346 */
    362347int gpt_write_partitions(gpt_label_t *label, service_id_t dev_handle)
    363348{
    364         int rc;
    365         size_t b_size;
    366        
    367349        /* comm_size of 4096 is ignored */
    368         rc = block_init(EXCHANGE_ATOMIC, dev_handle, 4096);
    369         if (rc != EOK && rc != EEXIST)
     350        int rc = block_init(EXCHANGE_ATOMIC, dev_handle, 4096);
     351        if ((rc != EOK) && (rc != EEXIST))
    370352                return rc;
    371353       
    372         rc = block_get_bsize(dev_handle, &b_size);
     354        size_t block_size;
     355        rc = block_get_bsize(dev_handle, &block_size);
    373356        if (rc != EOK)
    374357                goto fail;
    375358       
    376         aoff64_t n_blocks;
    377         rc = block_get_nblocks(dev_handle, &n_blocks);
     359        aoff64_t blocks;
     360        rc = block_get_nblocks(dev_handle, &blocks);
    378361        if (rc != EOK)
    379362                goto fail;
    380363       
    381         /* When we're creating a new label from scratch, we need to fill
    382          * the header with sensible defaults. */
    383         if (label->gpt == NULL) {
    384                 label->gpt = gpt_alloc_header(b_size);
    385         }
    386        
    387         uint32_t e_size = uint32_t_le2host(label->gpt->header->entry_size);
    388         size_t fillries = label->parts->fill > GPT_MIN_PART_NUM ? label->parts->fill : GPT_MIN_PART_NUM;
    389        
    390         if (e_size != sizeof(gpt_entry_t))
     364        if (label->gpt == NULL)
     365                label->gpt = gpt_alloc_header(block_size);
     366       
     367        uint32_t entry_size =
     368            uint32_t_le2host(label->gpt->header->entry_size);
     369        size_t fillries = (label->parts->fill > GPT_MIN_PART_NUM) ?
     370            label->parts->fill : GPT_MIN_PART_NUM;
     371       
     372        if (entry_size != sizeof(gpt_entry_t))
    391373                return ENOTSUP;
    392 
     374       
    393375        label->gpt->header->fillries = host2uint32_t_le(fillries);
    394         uint64_t arr_blocks = (fillries * sizeof(gpt_entry_t)) / b_size;
    395         uint64_t gpt_space = arr_blocks + GPT_HDR_BS + 1; /* +1 for Protective MBR */
     376       
     377        uint64_t arr_blocks = (fillries * sizeof(gpt_entry_t)) / block_size;
     378       
     379        /* Include Protective MBR */
     380        uint64_t gpt_space = arr_blocks + GPT_HDR_BS + 1;
     381       
    396382        label->gpt->header->first_usable_lba = host2uint64_t_le(gpt_space);
    397         label->gpt->header->last_usable_lba = host2uint64_t_le(n_blocks - gpt_space - 1);
     383        label->gpt->header->last_usable_lba =
     384            host2uint64_t_le(blocks - gpt_space - 1);
    398385       
    399386        /* Perform checks */
     
    402389                        continue;
    403390               
    404                 if (!check_encaps(p, n_blocks, gpt_space)) {
     391                if (!check_encaps(p, blocks, gpt_space)) {
    405392                        rc = ERANGE;
    406393                        goto fail;
     
    420407        }
    421408       
    422         label->gpt->header->pe_array_crc32 = host2uint32_t_le(compute_crc32(
    423                                        (uint8_t *) label->parts->part_array,
    424                                        fillries * e_size));
    425        
     409        label->gpt->header->pe_array_crc32 =
     410            host2uint32_t_le(compute_crc32((uint8_t *) label->parts->part_array,
     411            fillries * entry_size));
    426412       
    427413        /* Write to backup GPT partition array location */
    428         rc = block_write_direct(dev_handle, n_blocks - arr_blocks - 1,
    429                  arr_blocks, label->parts->part_array);
     414        rc = block_write_direct(dev_handle, blocks - arr_blocks - 1,
     415            arr_blocks, label->parts->part_array);
    430416        if (rc != EOK)
    431417                goto fail;
    432418       
    433419        /* Write to main GPT partition array location */
    434         rc = block_write_direct(dev_handle, uint64_t_le2host(label->gpt->header->entry_lba),
    435                  arr_blocks, label->parts->part_array);
     420        rc = block_write_direct(dev_handle,
     421            uint64_t_le2host(label->gpt->header->entry_lba),
     422            arr_blocks, label->parts->part_array);
    436423        if (rc != EOK)
    437424                goto fail;
     
    444431}
    445432
    446 /** Alloc new partition
    447  *
    448  * @return        returns pointer to the new partition or NULL
    449  *
    450  * Note: use either gpt_alloc_partition or gpt_get_partition.
     433/** Allocate a new partition
     434 *
     435 * Note: Use either gpt_alloc_partition() or gpt_get_partition().
    451436 * This returns a memory block (zero-filled) and needs gpt_add_partition()
    452437 * to be called to insert it into a partition array.
    453438 * Requires you to call gpt_free_partition afterwards.
    454  */
    455 gpt_part_t * gpt_alloc_partition(void)
    456 {
    457         gpt_part_t *p = malloc(sizeof(gpt_part_t));
    458         if (p == NULL)
     439 *
     440 * @return Pointer to the new partition or NULL.
     441 *
     442 */
     443gpt_part_t *gpt_alloc_partition(void)
     444{
     445        gpt_part_t *partition = malloc(sizeof(gpt_part_t));
     446        if (partition == NULL)
    459447                return NULL;
    460448       
    461         memset(p, 0, sizeof(gpt_part_t));
    462        
    463         return p;
    464 }
    465 
    466 /** Alloc new partition already inside the label
    467  *
    468  * @param label   label to carry new partition
    469  *
    470  * @return        returns pointer to the new partition or NULL on ENOMEM
    471  *
    472  * Note: use either gpt_alloc_partition or gpt_get_partition.
     449        memset(partition, 0, sizeof(gpt_part_t));
     450       
     451        return partition;
     452}
     453
     454/** Allocate a new partition already inside the label
     455 *
     456 * Note: Use either gpt_alloc_partition() or gpt_get_partition().
    473457 * This one returns a pointer to the first empty structure already
    474458 * inside the array, so don't call gpt_add_partition() afterwards.
    475459 * This is the one you will usually want.
    476  */
    477 gpt_part_t * gpt_get_partition(gpt_label_t *label)
    478 {
    479         gpt_part_t *p;
    480        
     460 *
     461 * @param label Label to carry new partition.
     462 *
     463 * @return Pointer to the new partition or NULL.
     464 *
     465 */
     466gpt_part_t *gpt_get_partition(gpt_label_t *label)
     467{
     468        gpt_part_t *partition;
    481469       
    482470        /* Find the first empty entry */
     
    487475                }
    488476               
    489                 p = label->parts->part_array + label->parts->fill++;
    490                
    491         } while (gpt_get_part_type(p) != GPT_PTE_UNUSED);
    492        
    493         return p;
     477                partition = label->parts->part_array + label->parts->fill++;
     478        } while (gpt_get_part_type(partition) != GPT_PTE_UNUSED);
     479       
     480        return partition;
    494481}
    495482
    496483/** Get partition already inside the label
    497484 *
    498  * @param label   label to carrying the partition
    499  * @param idx     index of the partition
    500  *
    501  * @return        returns pointer to the partition
    502  *                or NULL when out of range
    503  *
    504  * Note: For new partitions use either gpt_alloc_partition or
    505  * gpt_get_partition unless you want a partition at a specific place.
     485 * Note: For new partitions use either gpt_alloc_partition() or
     486 * gpt_get_partition() unless you want a partition at a specific place.
    506487 * This returns a pointer to a structure already inside the array,
    507488 * so don't call gpt_add_partition() afterwards.
     
    510491 * for indexes smaller than either 128 or the actual number of filled
    511492 * entries.
    512  */
    513 gpt_part_t * gpt_get_partition_at(gpt_label_t *label, size_t idx)
    514 {
    515         return NULL;
    516        
    517         if (idx >= GPT_MIN_PART_NUM && idx >= label->parts->fill)
     493 *
     494 * @param label Label to carrying the partition.
     495 * @param idx   Index of the partition.
     496 *
     497 * @return Pointer to the partition or NULL when out of range.
     498 *
     499 */
     500gpt_part_t *gpt_get_partition_at(gpt_label_t *label, size_t idx)
     501{
     502        if ((idx >= GPT_MIN_PART_NUM) && (idx >= label->parts->fill))
    518503                return NULL;
    519504       
     
    523508/** Copy partition into partition array
    524509 *
    525  * @param parts                 target label
    526  * @param partition             source partition to copy
    527  *
    528  * @return                              -1 on error, 0 otherwise
    529  *
    530  * Note: for use with gpt_alloc_partition() only. You will get
     510 * Note: For use with gpt_alloc_partition() only. You will get
    531511 * duplicates with gpt_get_partition().
    532  * Note: does not call gpt_free_partition()!
     512 * Note: Does not call gpt_free_partition()!
     513 *
     514 * @param parts     Target label
     515 * @param partition Source partition to copy
     516 *
     517 * @return EOK on succes, error code otherwise
     518 *
    533519 */
    534520int gpt_add_partition(gpt_label_t *label, gpt_part_t *partition)
    535521{
    536         gpt_part_t *p;
    537522        /* Find the first empty entry */
     523       
     524        gpt_part_t *part;
     525       
    538526        do {
    539527                if (label->parts->fill == label->parts->arr_size) {
     
    542530                }
    543531               
    544                 p = label->parts->part_array + label->parts->fill++;
    545                
    546         } while (gpt_get_part_type(p) != GPT_PTE_UNUSED);
    547        
    548        
    549         memcpy(p, partition, sizeof(gpt_entry_t));
    550        
    551        
     532                part = label->parts->part_array + label->parts->fill++;
     533        } while (gpt_get_part_type(part) != GPT_PTE_UNUSED);
     534       
     535        memcpy(part, partition, sizeof(gpt_entry_t));
    552536        return EOK;
    553537}
    554538
    555539/** Remove partition from array
    556  * @param label   label to remove from
    557  * @param idx     index of the partition to remove
    558  *
    559  * @return        EOK on success, ENOMEM on array reduction failure
    560  *
    561  * Note: even if it fails, the partition still gets removed. Only
     540 *
     541 * Note: Even if it fails, the partition still gets removed. Only
    562542 * reducing the array failed.
     543 *
     544 * @param label Label to remove from
     545 * @param idx   Index of the partition to remove
     546 *
     547 * @return EOK on success, ENOMEM on array reduction failure
     548 *
    563549 */
    564550int gpt_remove_partition(gpt_label_t *label, size_t idx)
     
    567553                return EINVAL;
    568554       
    569         /* 
    570          * FIXME!
     555        /*
     556         * FIXME:
    571557         * If we allow blank spots, we break the array. If we have more than
    572558         * 128 partitions in the array and then remove something from
    573559         * the first 128 partitions, we would forget to write the last one.
    574560         */
     561       
    575562        memset(label->parts->part_array + idx, 0, sizeof(gpt_entry_t));
    576563       
     
    578565                label->parts->fill = idx;
    579566       
    580         /*
    581          * FIXME! HOPEFULLY FIXED.
    582          * We cannot reduce the array so simply. We may have some partitions
    583          * there since we allow blank spots.
    584          */
    585         gpt_part_t * p;
    586        
    587         if (label->parts->fill > GPT_MIN_PART_NUM &&
    588             label->parts->fill < (label->parts->arr_size / 2) - GPT_IGNORE_FILL_NUM) {
    589                 for (p = gpt_get_partition_at(label, label->parts->arr_size / 2);
    590                      p < label->parts->part_array + label->parts->arr_size; ++p) {
    591                                 if (gpt_get_part_type(p) != GPT_PTE_UNUSED)
    592                                         return EOK;
     567        gpt_part_t *partition;
     568       
     569        if ((label->parts->fill > GPT_MIN_PART_NUM) &&
     570            (label->parts->fill < (label->parts->arr_size / 2) -
     571            GPT_IGNORE_FILL_NUM)) {
     572                for (partition = gpt_get_partition_at(label, label->parts->arr_size / 2);
     573                     partition < label->parts->part_array + label->parts->arr_size;
     574                     partition++) {
     575                        if (gpt_get_part_type(partition) != GPT_PTE_UNUSED)
     576                                return EOK;
    593577                }
    594578               
     
    596580                        return ENOMEM;
    597581        }
    598 
     582       
    599583        return EOK;
    600584}
     
    602586/** Free partition list
    603587 *
    604  * @param parts         partition list to be freed
    605  */
    606 void gpt_free_partitions(gpt_partitions_t * parts)
     588 * @param parts Partition list to be freed
     589 *
     590 */
     591void gpt_free_partitions(gpt_partitions_t *parts)
    607592{
    608593        free(parts->part_array);
     
    610595}
    611596
    612 /** Get partition type by linear search
    613  * (hopefully this doesn't get slow)
    614  */
    615 size_t gpt_get_part_type(gpt_part_t * p)
     597/** Get partition type */
     598size_t gpt_get_part_type(gpt_part_t *partition)
    616599{
    617600        size_t i;
    618601       
    619602        for (i = 0; gpt_ptypes[i].guid != NULL; i++) {
    620                 if (p->part_type[3] == get_byte(gpt_ptypes[i].guid +0) &&
    621                         p->part_type[2] == get_byte(gpt_ptypes[i].guid +2) &&
    622                         p->part_type[1] == get_byte(gpt_ptypes[i].guid +4) &&
    623                         p->part_type[0] == get_byte(gpt_ptypes[i].guid +6) &&
    624                        
    625                         p->part_type[5] == get_byte(gpt_ptypes[i].guid +8) &&
    626                         p->part_type[4] == get_byte(gpt_ptypes[i].guid +10) &&
    627                        
    628                         p->part_type[7] == get_byte(gpt_ptypes[i].guid +12) &&
    629                         p->part_type[6] == get_byte(gpt_ptypes[i].guid +14) &&
    630                        
    631                         p->part_type[8] == get_byte(gpt_ptypes[i].guid +16) &&
    632                         p->part_type[9] == get_byte(gpt_ptypes[i].guid +18) &&
    633                         p->part_type[10] == get_byte(gpt_ptypes[i].guid +20) &&
    634                         p->part_type[11] == get_byte(gpt_ptypes[i].guid +22) &&
    635                         p->part_type[12] == get_byte(gpt_ptypes[i].guid +24) &&
    636                         p->part_type[13] == get_byte(gpt_ptypes[i].guid +26) &&
    637                         p->part_type[14] == get_byte(gpt_ptypes[i].guid +28) &&
    638                         p->part_type[15] == get_byte(gpt_ptypes[i].guid +30))
    639                                 break;
     603                if ((partition->part_type[3] == get_byte(gpt_ptypes[i].guid + 0)) &&
     604                    (partition->part_type[2] == get_byte(gpt_ptypes[i].guid + 2)) &&
     605                    (partition->part_type[1] == get_byte(gpt_ptypes[i].guid + 4)) &&
     606                    (partition->part_type[0] == get_byte(gpt_ptypes[i].guid + 6)) &&
     607                    (partition->part_type[5] == get_byte(gpt_ptypes[i].guid + 8)) &&
     608                    (partition->part_type[4] == get_byte(gpt_ptypes[i].guid + 10)) &&
     609                    (partition->part_type[7] == get_byte(gpt_ptypes[i].guid + 12)) &&
     610                    (partition->part_type[6] == get_byte(gpt_ptypes[i].guid + 14)) &&
     611                    (partition->part_type[8] == get_byte(gpt_ptypes[i].guid + 16)) &&
     612                    (partition->part_type[9] == get_byte(gpt_ptypes[i].guid + 18)) &&
     613                    (partition->part_type[10] == get_byte(gpt_ptypes[i].guid + 20)) &&
     614                    (partition->part_type[11] == get_byte(gpt_ptypes[i].guid + 22)) &&
     615                    (partition->part_type[12] == get_byte(gpt_ptypes[i].guid + 24)) &&
     616                    (partition->part_type[13] == get_byte(gpt_ptypes[i].guid + 26)) &&
     617                    (partition->part_type[14] == get_byte(gpt_ptypes[i].guid + 28)) &&
     618                    (partition->part_type[15] == get_byte(gpt_ptypes[i].guid + 30)))
     619                        return i;
    640620        }
    641621       
     
    643623}
    644624
    645 /** Set partition type
    646  * @param p                     partition to be set
    647  * @param type          partition type to set
    648  *                                      - see our fine selection at gpt_ptypes to choose from
    649  */
    650 void gpt_set_part_type(gpt_part_t * p, size_t type)
     625/** Set partition type */
     626void gpt_set_part_type(gpt_part_t *partition, size_t type)
    651627{
    652628        /* Beware: first 3 blocks are byteswapped! */
    653         p->part_type[3] = get_byte(gpt_ptypes[type].guid +0);
    654         p->part_type[2] = get_byte(gpt_ptypes[type].guid +2);
    655         p->part_type[1] = get_byte(gpt_ptypes[type].guid +4);
    656         p->part_type[0] = get_byte(gpt_ptypes[type].guid +6);
    657                        
    658         p->part_type[5] = get_byte(gpt_ptypes[type].guid +8);
    659         p->part_type[4] = get_byte(gpt_ptypes[type].guid +10);
    660                        
    661         p->part_type[7] = get_byte(gpt_ptypes[type].guid +12);
    662         p->part_type[6] = get_byte(gpt_ptypes[type].guid +14);
    663                        
    664         p->part_type[8] = get_byte(gpt_ptypes[type].guid +16);
    665         p->part_type[9] = get_byte(gpt_ptypes[type].guid +18);
    666         p->part_type[10] = get_byte(gpt_ptypes[type].guid +20);
    667         p->part_type[11] = get_byte(gpt_ptypes[type].guid +22);
    668         p->part_type[12] = get_byte(gpt_ptypes[type].guid +24);
    669         p->part_type[13] = get_byte(gpt_ptypes[type].guid +26);
    670         p->part_type[14] = get_byte(gpt_ptypes[type].guid +28);
    671         p->part_type[15] = get_byte(gpt_ptypes[type].guid +30);
     629        partition->part_type[3] = get_byte(gpt_ptypes[type].guid + 0);
     630        partition->part_type[2] = get_byte(gpt_ptypes[type].guid + 2);
     631        partition->part_type[1] = get_byte(gpt_ptypes[type].guid + 4);
     632        partition->part_type[0] = get_byte(gpt_ptypes[type].guid + 6);
     633       
     634        partition->part_type[5] = get_byte(gpt_ptypes[type].guid + 8);
     635        partition->part_type[4] = get_byte(gpt_ptypes[type].guid + 10);
     636       
     637        partition->part_type[7] = get_byte(gpt_ptypes[type].guid + 12);
     638        partition->part_type[6] = get_byte(gpt_ptypes[type].guid + 14);
     639       
     640        partition->part_type[8] = get_byte(gpt_ptypes[type].guid + 16);
     641        partition->part_type[9] = get_byte(gpt_ptypes[type].guid + 18);
     642        partition->part_type[10] = get_byte(gpt_ptypes[type].guid + 20);
     643        partition->part_type[11] = get_byte(gpt_ptypes[type].guid + 22);
     644        partition->part_type[12] = get_byte(gpt_ptypes[type].guid + 24);
     645        partition->part_type[13] = get_byte(gpt_ptypes[type].guid + 26);
     646        partition->part_type[14] = get_byte(gpt_ptypes[type].guid + 28);
     647        partition->part_type[15] = get_byte(gpt_ptypes[type].guid + 30);
    672648}
    673649
    674650/** Get partition starting LBA */
    675 uint64_t gpt_get_start_lba(gpt_part_t * p)
    676 {
    677         return uint64_t_le2host(p->start_lba);
     651uint64_t gpt_get_start_lba(gpt_part_t *partition)
     652{
     653        return uint64_t_le2host(partition->start_lba);
    678654}
    679655
    680656/** Set partition starting LBA */
    681 void gpt_set_start_lba(gpt_part_t * p, uint64_t start)
    682 {
    683         p->start_lba = host2uint64_t_le(start);
     657void gpt_set_start_lba(gpt_part_t *partition, uint64_t start)
     658{
     659        partition->start_lba = host2uint64_t_le(start);
    684660}
    685661
    686662/** Get partition ending LBA */
    687 uint64_t gpt_get_end_lba(gpt_part_t * p)
    688 {
    689         return uint64_t_le2host(p->end_lba);
     663uint64_t gpt_get_end_lba(gpt_part_t *partition)
     664{
     665        return uint64_t_le2host(partition->end_lba);
    690666}
    691667
    692668/** Set partition ending LBA */
    693 void gpt_set_end_lba(gpt_part_t * p, uint64_t end)
    694 {
    695         p->end_lba = host2uint64_t_le(end);
     669void gpt_set_end_lba(gpt_part_t *partition, uint64_t end)
     670{
     671        partition->end_lba = host2uint64_t_le(end);
    696672}
    697673
    698674/** Get partition name */
    699 unsigned char * gpt_get_part_name(gpt_part_t * p)
    700 {
    701         return p->part_name;
     675unsigned char * gpt_get_part_name(gpt_part_t *partition)
     676{
     677        return partition->part_name;
    702678}
    703679
    704680/** Copy partition name */
    705 void gpt_set_part_name(gpt_part_t *p, char *name, size_t length)
     681void gpt_set_part_name(gpt_part_t *partition, char *name, size_t length)
    706682{
    707683        if (length >= 72)
    708684                length = 71;
    709 
    710         memcpy(p->part_name, name, length);
    711         p->part_name[length] = '\0';
     685       
     686        memcpy(partition->part_name, name, length);
     687        partition->part_name[length] = '\0';
    712688}
    713689
    714690/** Get partition attribute */
    715 bool gpt_get_flag(gpt_part_t * p, GPT_ATTR flag)
    716 {
    717         return (p->attributes & (((uint64_t) 1) << flag)) ? 1 : 0;
     691bool gpt_get_flag(gpt_part_t *partition, gpt_attr_t flag)
     692{
     693        return (partition->attributes & (((uint64_t) 1) << flag)) ? 1 : 0;
    718694}
    719695
    720696/** Set partition attribute */
    721 void gpt_set_flag(gpt_part_t * p, GPT_ATTR flag, bool value)
    722 {
    723         uint64_t attr = p->attributes;
    724 
     697void gpt_set_flag(gpt_part_t *partition, gpt_attr_t flag, bool value)
     698{
     699        uint64_t attr = partition->attributes;
     700       
    725701        if (value)
    726702                attr = attr | (((uint64_t) 1) << flag);
    727703        else
    728704                attr = attr ^ (attr & (((uint64_t) 1) << flag));
    729 
    730         p->attributes = attr;
     705       
     706        partition->attributes = attr;
    731707}
    732708
    733709/** Generate a new pseudo-random UUID
    734  * @param uuid Pointer to the UUID to overwrite.
    735  */
    736 void gpt_set_random_uuid(uint8_t * uuid)
     710 *
     711 * FIXME: This UUID generator is not compliant with RFC 4122.
     712 *
     713 */
     714void gpt_set_random_uuid(uint8_t *uuid)
    737715{
    738716        srandom((unsigned int) (size_t) uuid);
    739717       
    740         unsigned int i;
    741         for (i = 0; i < 16/sizeof(long int); ++i)
    742                 ((long int *)uuid)[i] = random();
    743        
     718        for (size_t i = 0; i < 16; i++)
     719                uuid[i] = random();
    744720}
    745721
     
    747723uint64_t gpt_get_next_aligned(uint64_t addr, unsigned int alignment)
    748724{
    749         uint64_t div = addr / alignment;
    750         return (div + 1) * alignment;
    751 }
    752 
    753 /* Internal functions follow */
    754 
    755 static int load_and_check_header(service_id_t dev_handle, aoff64_t addr, size_t b_size, gpt_header_t * header)
    756 {
    757         int rc;
    758 
    759         rc = block_read_direct(dev_handle, addr, GPT_HDR_BS, header);
     725        return ALIGN_UP(addr + 1, alignment);
     726}
     727
     728static int load_and_check_header(service_id_t dev_handle, aoff64_t addr,
     729    size_t block_size, gpt_header_t *header)
     730{
     731        int rc = block_read_direct(dev_handle, addr, GPT_HDR_BS, header);
    760732        if (rc != EOK)
    761733                return rc;
    762 
    763         unsigned int i;
     734       
    764735        /* Check the EFI signature */
    765         for (i = 0; i < 8; ++i) {
     736        for (unsigned int i = 0; i < 8; i++) {
    766737                if (header->efi_signature[i] != efi_signature[i])
    767738                        return EINVAL;
    768739        }
    769 
     740       
    770741        /* Check the CRC32 of the header */
    771742        uint32_t crc = header->header_crc32;
    772743        header->header_crc32 = 0;
     744       
    773745        if (crc != compute_crc32((uint8_t *) header, header->header_size))
    774746                return EBADCHECKSUM;
    775747        else
    776748                header->header_crc32 = crc;
    777 
     749       
    778750        /* Check for zeroes in the rest of the block */
    779         for (i = sizeof(gpt_header_t); i < b_size; ++i) {
     751        for (size_t i = sizeof(gpt_header_t); i < block_size; i++) {
    780752                if (((uint8_t *) header)[i] != 0)
    781753                        return EINVAL;
    782754        }
    783 
     755       
    784756        return EOK;
    785757}
    786758
    787 static gpt_partitions_t * alloc_part_array(uint32_t num)
    788 {
    789         gpt_partitions_t * res = malloc(sizeof(gpt_partitions_t));
    790         if (res == NULL) {
    791                 errno = ENOMEM;
     759static gpt_partitions_t *alloc_part_array(uint32_t num)
     760{
     761        gpt_partitions_t *res = malloc(sizeof(gpt_partitions_t));
     762        if (res == NULL)
    792763                return NULL;
    793         }
    794764       
    795765        uint32_t size = num > GPT_BASE_PART_NUM ? num : GPT_BASE_PART_NUM;
     
    797767        if (res->part_array == NULL) {
    798768                free(res);
    799                 errno = ENOMEM;
    800769                return NULL;
    801770        }
     
    805774        res->fill = 0;
    806775        res->arr_size = num;
    807 
     776       
    808777        return res;
    809778}
    810779
    811 static int extend_part_array(gpt_partitions_t * p)
    812 {
    813         size_t nsize = p->arr_size * 2;
    814         gpt_entry_t * tmp = malloc(nsize * sizeof(gpt_entry_t));
    815         if (tmp == NULL) {
    816                 errno = ENOMEM;
    817                 return -1;
    818         }
    819        
    820         memcpy(tmp, p->part_array, p->fill * sizeof(gpt_entry_t));
    821         free(p->part_array);
    822         p->part_array = tmp;
    823         p->arr_size = nsize;
    824 
    825         return 0;
    826 }
    827 
    828 static int reduce_part_array(gpt_partitions_t * p)
    829 {
    830         if (p->arr_size > GPT_MIN_PART_NUM) {
    831                 unsigned int nsize = p->arr_size / 2;
     780static int extend_part_array(gpt_partitions_t *partition)
     781{
     782        size_t nsize = partition->arr_size * 2;
     783        gpt_entry_t *entry = malloc(nsize * sizeof(gpt_entry_t));
     784        if (entry == NULL)
     785                return ENOMEM;
     786       
     787        memcpy(entry, partition->part_array, partition->fill *
     788            sizeof(gpt_entry_t));
     789        free(partition->part_array);
     790       
     791        partition->part_array = entry;
     792        partition->arr_size = nsize;
     793       
     794        return EOK;
     795}
     796
     797static int reduce_part_array(gpt_partitions_t *partition)
     798{
     799        if (partition->arr_size > GPT_MIN_PART_NUM) {
     800                unsigned int nsize = partition->arr_size / 2;
    832801                nsize = nsize > GPT_MIN_PART_NUM ? nsize : GPT_MIN_PART_NUM;
    833                 gpt_entry_t * tmp = malloc(nsize * sizeof(gpt_entry_t));
    834                 if (tmp == NULL)
     802               
     803                gpt_entry_t *entry = malloc(nsize * sizeof(gpt_entry_t));
     804                if (entry == NULL)
    835805                        return ENOMEM;
    836 
    837                 memcpy(tmp, p->part_array, p->fill < nsize ? p->fill : nsize);
    838                 free(p->part_array);
    839                 p->part_array = tmp;
    840                 p->arr_size = nsize;
    841         }
    842 
    843         return 0;
    844 }
    845 
    846 /* Parse a byte from a string in hexadecimal
    847  * i.e., "FF" => 255
    848  */
    849 static uint8_t get_byte(const char * c)
     806               
     807                memcpy(entry, partition->part_array,
     808                    partition->fill < nsize ? partition->fill : nsize);
     809                free(partition->part_array);
     810               
     811                partition->part_array = entry;
     812                partition->arr_size = nsize;
     813        }
     814       
     815        return EOK;
     816}
     817
     818/* Parse a byte from a string in hexadecimal */
     819static uint8_t get_byte(const char *c)
    850820{
    851821        uint8_t val = 0;
    852         char hex[3] = {*c, *(c+1), 0};
    853        
    854         errno = str_uint8_t(hex, NULL, 16, false, &val);
     822        char hex[3] = {*c, *(c + 1), 0};
     823       
     824        str_uint8_t(hex, NULL, 16, false, &val);
    855825        return val;
    856826}
    857827
    858 static bool check_overlap(gpt_part_t * p1, gpt_part_t * p2)
    859 {
    860         if (gpt_get_start_lba(p1) < gpt_get_start_lba(p2) && gpt_get_end_lba(p1) < gpt_get_start_lba(p2)) {
     828static bool check_overlap(gpt_part_t *part1, gpt_part_t *part2)
     829{
     830        if ((gpt_get_start_lba(part1) < gpt_get_start_lba(part2)) &&
     831            (gpt_get_end_lba(part1) < gpt_get_start_lba(part2)))
    861832                return false;
    862         } else if (gpt_get_start_lba(p1) > gpt_get_start_lba(p2) && gpt_get_end_lba(p2) < gpt_get_start_lba(p1)) {
     833       
     834        if ((gpt_get_start_lba(part1) > gpt_get_start_lba(part2)) &&
     835            (gpt_get_end_lba(part2) < gpt_get_start_lba(part1)))
    863836                return false;
    864         }
    865 
     837       
    866838        return true;
    867839}
    868840
    869 static bool check_encaps(gpt_part_t *p, uint64_t n_blocks, uint64_t first_lba)
    870 {
    871         /*
    872          * We allow "<=" in the second expression because it lacks MBR so
    873          * it's by 1 block smaller.
     841static bool check_encaps(gpt_part_t *part, uint64_t blocks,
     842    uint64_t first_lba)
     843{
     844        /*
     845         * We allow "<=" in the second expression because it lacks
     846         * MBR so it is smaller by 1 block.
    874847         */
    875         if (gpt_get_start_lba(p) >= first_lba && gpt_get_end_lba(p) <= n_blocks - first_lba)
     848        if ((gpt_get_start_lba(part) >= first_lba) &&
     849            (gpt_get_end_lba(part) <= blocks - first_lba))
    876850                return true;
    877851       
  • uspace/lib/gpt/libgpt.h

    rd51beba3 r6453e306  
    11/*
    22 * Copyright (c) 2009 Jiri Svoboda
    3  * Copyright (c) 2011, 2012, 2013 Dominik Taborsky
     3 * Copyright (c) 2011-2013 Dominik Taborsky
    44 * All rights reserved.
    55 *
     
    3737#define LIBGPT_LIBGPT_H_
    3838
    39 #define LIBGPT_NAME     "libgpt"
    40 
    4139#include <loc.h>
    4240#include <sys/types.h>
    43 
    4441#include "gpt.h"
    4542
    4643/** Block address of GPT header. */
    47 #define GPT_HDR_BA      1
     44#define GPT_HDR_BA  1
     45
    4846/** Block size of GPT header. */
    49 #define GPT_HDR_BS      1
     47#define GPT_HDR_BS  1
     48
    5049/** Minimum number of GPT partition entries */
    51 #define GPT_MIN_PART_NUM 128
     50#define GPT_MIN_PART_NUM  128
     51
    5252/** Basic number of GPT partition entries */
    53 #define GPT_BASE_PART_NUM (GPT_MIN_PART_NUM)
     53#define GPT_BASE_PART_NUM  (GPT_MIN_PART_NUM)
     54
    5455/** How much fill we ignore before resizing partition array */
    55 #define GPT_IGNORE_FILL_NUM 10
     56#define GPT_IGNORE_FILL_NUM  10
    5657
    5758/** Unused partition entry */
    58 #define GPT_PTE_UNUSED 0
     59#define GPT_PTE_UNUSED  0
     60
     61/** Raw GPT header.
     62 *
     63 * Uses more bytes than sizeof(gpt_header_t).
     64 */
     65typedef struct {
     66        gpt_header_t *header;
     67} gpt_t;
     68
     69typedef gpt_entry_t gpt_part_t;
     70
     71typedef struct {
     72        /** Number of entries */
     73        size_t fill;
     74       
     75        /** Size of the array */
     76        size_t arr_size;
     77       
     78        /** Resizable partition array */
     79        gpt_part_t *part_array;
     80} gpt_partitions_t;
     81
     82typedef struct {
     83        gpt_t *gpt;
     84        gpt_partitions_t *parts;
     85        service_id_t device;
     86} gpt_label_t;
     87
     88typedef struct {
     89        const char *desc;
     90        const char *guid;
     91} partition_type_t;
    5992
    6093/** GPT header signature ("EFI PART" in ASCII) */
     
    6295extern const uint8_t revision[4];
    6396
    64 typedef struct {
    65         /** Raw header. Has more bytes alloced than sizeof(gpt_header_t)!
    66          * See gpt_alloc_header() to know why. */
    67         gpt_header_t *header;
    68 } gpt_t;
     97extern const partition_type_t gpt_ptypes[];
    6998
    70 typedef gpt_entry_t gpt_part_t;
    71 
    72 typedef struct gpt_parts {
    73         /** Number of entries */
    74         size_t fill;
    75         /** Size of the array */
    76         size_t arr_size;
    77         /** Resizable partition array */
    78         gpt_entry_t *part_array;
    79 } gpt_partitions_t;
    80 
    81 
    82 typedef struct gpt_table {
    83         gpt_t *gpt;
    84         gpt_partitions_t *parts;
    85         service_id_t device;
    86 } gpt_label_t;
    87 
    88 struct partition_type {
    89         const char *desc;
    90         const char *guid;
    91 };
    92 
    93 extern const struct partition_type gpt_ptypes[];
    94 
    95 extern gpt_label_t * gpt_alloc_label(void);
     99extern gpt_label_t *gpt_alloc_label(void);
    96100extern void gpt_free_label(gpt_label_t *);
    97101
    98 extern gpt_t * gpt_alloc_header(size_t);
    99 extern int     gpt_read_header(gpt_label_t *, service_id_t);
    100 extern int     gpt_write_header(gpt_label_t *, service_id_t);
     102extern gpt_t *gpt_alloc_header(size_t);
     103extern int gpt_read_header(gpt_label_t *, service_id_t);
     104extern int gpt_write_header(gpt_label_t *, service_id_t);
    101105
    102 extern gpt_partitions_t * gpt_alloc_partitions(void);
    103 extern int             gpt_read_partitions (gpt_label_t *);
    104 extern int             gpt_write_partitions(gpt_label_t *, service_id_t);
    105 extern gpt_part_t *    gpt_alloc_partition (void);
    106 extern gpt_part_t *    gpt_get_partition   (gpt_label_t *);
    107 extern gpt_part_t *    gpt_get_partition_at(gpt_label_t *, size_t);
    108 extern int             gpt_add_partition   (gpt_label_t *, gpt_part_t *);
    109 extern int             gpt_remove_partition(gpt_label_t *, size_t);
     106extern gpt_partitions_t *gpt_alloc_partitions(void);
     107extern int gpt_read_partitions(gpt_label_t *);
     108extern int gpt_write_partitions(gpt_label_t *, service_id_t);
     109extern gpt_part_t *gpt_alloc_partition(void);
     110extern gpt_part_t *gpt_get_partition(gpt_label_t *);
     111extern gpt_part_t *gpt_get_partition_at(gpt_label_t *, size_t);
     112extern int gpt_add_partition(gpt_label_t *, gpt_part_t *);
     113extern int gpt_remove_partition(gpt_label_t *, size_t);
    110114
    111 extern size_t          gpt_get_part_type(gpt_part_t *);
    112 extern void            gpt_set_part_type(gpt_part_t *, size_t);
    113 extern void            gpt_set_start_lba(gpt_part_t *, uint64_t);
    114 extern uint64_t        gpt_get_start_lba(gpt_part_t *);
    115 extern void            gpt_set_end_lba  (gpt_part_t *, uint64_t);
    116 extern uint64_t        gpt_get_end_lba  (gpt_part_t *);
    117 extern unsigned char * gpt_get_part_name(gpt_part_t *);
    118 extern void            gpt_set_part_name(gpt_part_t *, char *, size_t);
    119 extern bool            gpt_get_flag     (gpt_part_t *, GPT_ATTR);
    120 extern void            gpt_set_flag     (gpt_part_t *, GPT_ATTR, bool);
     115extern size_t gpt_get_part_type(gpt_part_t *);
     116extern void gpt_set_part_type(gpt_part_t *, size_t);
     117extern void gpt_set_start_lba(gpt_part_t *, uint64_t);
     118extern uint64_t gpt_get_start_lba(gpt_part_t *);
     119extern void gpt_set_end_lba(gpt_part_t *, uint64_t);
     120extern uint64_t gpt_get_end_lba(gpt_part_t *);
     121extern unsigned char *gpt_get_part_name(gpt_part_t *);
     122extern void gpt_set_part_name(gpt_part_t *, char *, size_t);
     123extern bool gpt_get_flag(gpt_part_t *, gpt_attr_t);
     124extern void gpt_set_flag(gpt_part_t *, gpt_attr_t, bool);
    121125
    122 extern void            gpt_set_random_uuid(uint8_t *);
    123 extern uint64_t        gpt_get_next_aligned(uint64_t, unsigned int);
     126extern void gpt_set_random_uuid(uint8_t *);
     127extern uint64_t gpt_get_next_aligned(uint64_t, unsigned int);
    124128
    125129
    126130#define gpt_part_foreach(label, iterator) \
    127                 for(gpt_part_t * iterator = (label)->parts->part_array; \
    128                     iterator < (label)->parts->part_array + (label)->parts->arr_size; ++iterator)
     131        for (gpt_part_t *iterator = (label)->parts->part_array; \
     132            iterator < (label)->parts->part_array + (label)->parts->arr_size; \
     133            iterator++)
    129134
    130135extern void gpt_free_gpt(gpt_t *);
     
    132137
    133138#endif
    134 
  • uspace/lib/mbr/Makefile

    rd51beba3 r6453e306  
    2828
    2929USPACE_PREFIX = ../..
    30 EXTRA_CFLAGS = -I$(LIBBLOCK_PREFIX) -DDEBUG_CONFIG
     30EXTRA_CFLAGS = -I$(LIBBLOCK_PREFIX)
    3131LIBRARY = libmbr
    3232
  • uspace/lib/mbr/libmbr.c

    rd51beba3 r6453e306  
    11/*
    2  * Copyright (c) 2011, 2012, 2013 Dominik Taborsky
     2 * Copyright (c) 2011-2013 Dominik Taborsky
    33 * All rights reserved.
    44 *
     
    2727 */
    2828
    29  /** @addtogroup libmbr
     29/** @addtogroup libmbr
    3030 * @{
    3131 */
     
    4343#include <stdlib.h>
    4444#include <str_error.h>
    45 
     45#include <align.h>
    4646#include "libmbr.h"
    4747
    48 static br_block_t * alloc_br(void);
     48static br_block_t *alloc_br(void);
    4949static int decode_part(pt_entry_t *, mbr_part_t *, uint32_t);
    5050static int decode_logical(mbr_label_t *, mbr_part_t *);
     
    5757
    5858/** Allocate and initialize mbr_label_t structure */
    59 mbr_label_t * mbr_alloc_label(void)
     59mbr_label_t *mbr_alloc_label(void)
    6060{
    6161        mbr_label_t *label = malloc(sizeof(mbr_label_t));
     
    8888
    8989/** Allocate memory for mbr_t */
    90 mbr_t * mbr_alloc_mbr(void)
     90mbr_t *mbr_alloc_mbr(void)
    9191{
    9292        return malloc(sizeof(mbr_t));
     
    9494
    9595/** Read MBR from specific device
    96  * @param   label       label to write data to
    97  * @param   dev_handle  device to read MBR from
    98  *
    99  * @return                              EOK on success, error code on error
     96 *
     97 * @param label      Label to be read.
     98 * @param dev_handle Device to read MBR from.
     99 *
     100 * @return EOK on success, error code on error.
     101 *
    100102 */
    101103int mbr_read_mbr(mbr_label_t *label, service_id_t dev_handle)
    102104{       
    103         int rc;
    104        
    105105        if (label->mbr == NULL) {
    106106                label->mbr = mbr_alloc_mbr();
    107                 if (label->mbr == NULL) {
     107                if (label->mbr == NULL)
    108108                        return ENOMEM;
    109                 }
    110         }
    111 
    112         rc = block_init(EXCHANGE_ATOMIC, dev_handle, 512);
     109        }
     110       
     111        int rc = block_init(EXCHANGE_ATOMIC, dev_handle, 512);
    113112        if (rc != EOK)
    114113                return rc;
    115 
    116         rc = block_read_direct(dev_handle, 0, 1, &(label->mbr->raw_data));
     114       
     115        rc = block_read_direct(dev_handle, 0, 1, &label->mbr->raw_data);
    117116        block_fini(dev_handle);
    118117        if (rc != EOK)
    119118                return rc;
    120 
     119       
    121120        label->device = dev_handle;
    122 
     121       
    123122        return EOK;
    124123}
    125124
    126 /** Write mbr to disk
    127  * @param label                 MBR to be written
    128  * @param dev_handle    device handle to write MBR to (may be different
    129  *                                                      from the device in 'mbr')
    130  *
    131  * @return                              0 on success, otherwise libblock error code
     125/** Write MBR to specific device
     126 *
     127 * @param label      Label to be written.
     128 * @param dev_handle Device to write MBR to.
     129 *
     130 * @return EOK on success, error code on error.
     131 *
    132132 */
    133133int mbr_write_mbr(mbr_label_t *label, service_id_t dev_handle)
    134134{
    135         int rc;
    136 
    137         rc = block_init(EXCHANGE_ATOMIC, dev_handle, 512);
    138         if (rc != EOK) {
     135        int rc = block_init(EXCHANGE_ATOMIC, dev_handle, 512);
     136        if (rc != EOK)
    139137                return rc;
    140         }
    141 
    142         rc = block_write_direct(dev_handle, 0, 1, &(label->mbr->raw_data));
     138       
     139        rc = block_write_direct(dev_handle, 0, 1, &label->mbr->raw_data);
    143140        block_fini(dev_handle);
    144         if (rc != EOK) {
    145                 return rc;
    146         }
    147 
    148         return EOK;
    149 }
    150 
    151 /** Decide whether this is an actual MBR or a Protective MBR from GPT
    152  *
    153  * @param mbr           the actual MBR to decide upon
    154  *
    155  * @return                      1 if MBR, 0 if GPT
     141       
     142        return rc;
     143}
     144
     145/** Decide whether this is an actual MBR or a Protective MBR for GPT
     146 *
     147 * @param label Label to decide upon.
     148 *
     149 * @return True if MBR.
     150 * @return False if Protective MBR for GPT.
     151 *
    156152 */
    157153int mbr_is_mbr(mbr_label_t *label)
    158154{
    159         return (label->mbr->raw_data.pte[0].ptype != PT_GPT) ? 1 : 0;
    160 }
    161 
    162 /** Parse partitions from MBR, freeing previous partitions if any
    163  * NOTE: it is assumed mbr_read_mbr(label) was called before.
    164  * @param label  MBR to be parsed
    165  *
    166  * @return       linked list of partitions or NULL on error
     155        return (label->mbr->raw_data.pte[0].ptype != PT_GPT);
     156}
     157
     158/** Parse partitions from MBR (freeing previous partitions if any)
     159 *
     160 * It is assumed that mbr_read_mbr() was called before.
     161 *
     162 * @param label Label to be parsed.
     163 *
     164 * @return EOK on success, error code on error.
     165 *
    167166 */
    168167int mbr_read_partitions(mbr_label_t *label)
    169168{
    170         if (label == NULL || label->mbr == NULL)
     169        if ((label == NULL) || (label->mbr == NULL))
    171170                return EINVAL;
    172        
    173         int rc, rc_ext;
    174         unsigned int i;
    175         mbr_part_t *p;
    176         mbr_part_t *ext = NULL;
    177171       
    178172        if (label->parts != NULL)
     
    180174       
    181175        label->parts = mbr_alloc_partitions();
    182         if (label->parts == NULL) {
     176        if (label->parts == NULL)
    183177                return ENOMEM;
    184         }
     178       
     179        mbr_part_t *extended = NULL;
    185180       
    186181        /* Generate the primary partitions */
    187         for (i = 0; i < N_PRIMARY; ++i) {
     182        for (unsigned int i = 0; i < N_PRIMARY; i++) {
    188183                if (label->mbr->raw_data.pte[i].ptype == PT_UNUSED)
    189184                        continue;
    190185               
    191                 p = mbr_alloc_partition();
    192                 if (p == NULL) {
    193                         printf(LIBMBR_NAME ": Error on memory allocation.\n");
     186                mbr_part_t *partition = mbr_alloc_partition();
     187                if (partition == NULL) {
    194188                        mbr_free_partitions(label->parts);
    195189                        return ENOMEM;
    196190                }
    197191               
    198                 rc_ext = decode_part(&(label->mbr->raw_data.pte[i]), p, 0);
    199                 mbr_set_flag(p, ST_LOGIC, false);
    200                 rc = mbr_add_partition(label, p);
     192                int is_extended =
     193                    decode_part(&label->mbr->raw_data.pte[i], partition, 0);
     194               
     195                mbr_set_flag(partition, ST_LOGIC, false);
     196               
     197                int rc = mbr_add_partition(label, partition);
    201198                if (rc != ERR_OK) {
    202                         printf(LIBMBR_NAME ": Error occured during decoding the MBR. (%d)\n" \
    203                                LIBMBR_NAME ": MBR is invalid.\n", rc);
    204199                        mbr_free_partitions(label->parts);
    205200                        return EINVAL;
    206201                }
    207202               
    208                 if (rc_ext) {
    209                         ext = p;
    210                         label->parts->l_extended = &p->link;
    211                 }
    212         }
    213        
    214         /* Fill in the primary partitions and generate logical ones, if any */
    215         rc = decode_logical(label, ext);
    216         if (rc != EOK) {
    217                 printf(LIBMBR_NAME ": Error during decoding logical partitions: %d - %s.\n" \
    218                            LIBMBR_NAME ": Partition list may be incomplete.\n", rc, str_error(rc));
    219                 return rc;
    220         }
    221        
    222         return EOK;
     203                if (is_extended) {
     204                        extended = partition;
     205                        label->parts->l_extended = &partition->link;
     206                }
     207        }
     208       
     209        /* Fill in the primary partitions and generate logical ones (if any) */
     210        return decode_logical(label, extended);
    223211}
    224212
    225213/** Write MBR and partitions to device
    226  * @param label        label to write
    227  * @param dev_handle   device to write the data to
    228  *
    229  * @return             returns EOK on succes, specific error code otherwise
     214 *
     215 * @param label      Label to write.
     216 * @param dev_handle Device to write the data to.
     217 *
     218 * @return EOK on success, specific error code otherwise.
     219 *
    230220 */
    231221int mbr_write_partitions(mbr_label_t *label, service_id_t dev_handle)
     
    237227                label->mbr = mbr_alloc_mbr();
    238228       
    239         int i = 0;
    240         int rc;
    241         mbr_part_t *p;
    242         mbr_part_t *ext = (label->parts->l_extended == NULL) ? NULL
    243                                         : list_get_instance(label->parts->l_extended, mbr_part_t, link);
    244        
    245         rc = block_init(EXCHANGE_ATOMIC, dev_handle, 512);
    246         if (rc != EOK) {
    247                 printf(LIBMBR_NAME ": Error while initializing libblock: %d - %s.\n", rc, str_error(rc));
     229        int rc = block_init(EXCHANGE_ATOMIC, dev_handle, 512);
     230        if (rc != EOK)
    248231                return rc;
    249         }
    250        
    251         link_t *l = label->parts->list.head.next;
    252        
    253         /* Encoding primary partitions */
    254         for (i = 0; i < N_PRIMARY; i++) {
    255                 p = list_get_instance(l, mbr_part_t, link);     
    256                 encode_part(p, &(label->mbr->raw_data.pte[i]), 0, false);
    257                 l = l->next;
    258         }
    259        
    260         label->mbr->raw_data.signature = host2uint16_t_le(BR_SIGNATURE);
    261        
    262         /* Writing MBR */
    263         rc = block_write_direct(dev_handle, 0, 1, &(label->mbr->raw_data));
    264         if (rc != EOK) {
    265                 printf(LIBMBR_NAME ": Error while writing MBR : %d - %s.\n", rc, str_error(rc));
     232       
     233        mbr_part_t *partition = NULL;
     234        mbr_part_t *extended = NULL;
     235       
     236        if (label->parts->l_extended != NULL)
     237                extended = list_get_instance(label->parts->l_extended,
     238                    mbr_part_t, link);
     239       
     240        link_t *link = label->parts->list.head.next;
     241       
     242        /* Encode primary partitions */
     243        for (unsigned int i = 0; i < N_PRIMARY; i++) {
     244                partition = list_get_instance(link, mbr_part_t, link);
     245               
     246                encode_part(partition, &label->mbr->raw_data.pte[i], 0, false);
     247                link = link->next;
     248        }
     249       
     250        /* Write MBR */
     251        rc = block_write_direct(dev_handle, 0, 1, &label->mbr->raw_data);
     252        if ((rc != EOK) || (extended == NULL))
    266253                goto end;
    267         }
    268        
    269         if (ext == NULL) {
    270                 rc = EOK;
     254       
     255        uint32_t base = extended->start_addr;
     256        mbr_part_t *prev_partition;
     257       
     258        /* Encode and write first logical partition */
     259        if (link != &label->parts->list.head) {
     260                partition = list_get_instance(link, mbr_part_t, link);
     261               
     262                partition->ebr_addr = base;
     263                encode_part(partition, &partition->ebr->pte[0], base, false);
     264                link = link->next;
     265        } else {
     266                /*
     267                 * If there was an extended partition but no logical partitions,
     268                 * we should overwrite the space where the first logical
     269                 * partitions's EBR would have been. There might be some
     270                 * garbage from the past.
     271                 */
     272               
     273                br_block_t *br = alloc_br();
     274                rc = block_write_direct(dev_handle, base, 1, br);
     275                if (rc != EOK)
     276                        goto end;
     277               
     278                free(br);
    271279                goto end;
    272280        }
    273281       
    274         uint32_t base = ext->start_addr;
    275         mbr_part_t *prev_p;
    276        
    277         /* Note for future changes: Some thought has been put into design
    278          * and implementation. If you don't have to change it, don't. Other
    279          * designs have been tried, this came out as the least horror with
    280          * as much power over it as you can get. */
    281        
    282         /* Encoding and writing first logical partition */
    283         if (l != &(label->parts->list.head)) {
    284                 p = list_get_instance(l, mbr_part_t, link);
    285                 p->ebr_addr = base;
    286                 encode_part(p, &(p->ebr->pte[0]), base, false);
    287                 l = l->next;
    288         } else {
    289                 /* If there was an extended but no logical, we should overwrite
    290                  * the space where the first logical's EBR would have been. There
    291                  * might be some garbage from the past. */
    292                 br_block_t * tmp = alloc_br();
    293                 rc = block_write_direct(dev_handle, base, 1, tmp);
    294                 if (rc != EOK) {
    295                         printf(LIBMBR_NAME ": Error while writing EBR: %d - %s.\n", rc, str_error(rc));
    296                         goto end;
    297                 }
    298                 free(tmp);
    299                 rc = EOK;
    300                 goto end;
    301         }
    302        
    303         prev_p = p;
    304        
    305         /* Check EBR addresses
    306          * This piece of code saves previous EBR placements from other
    307          * software. But if our user modifies the logical partition chain,
    308          * we have to fix those placements if needed.*/
    309         link_t *l_ebr = l;
    310         link_t *l_iter;
    311         mbr_part_t *tmp = mbr_alloc_partition();
    312         tmp->length = 1;
    313         while (l_ebr != &(label->parts->list.head)) {
    314                 p = list_get_instance(l_ebr, mbr_part_t, link);
    315                 tmp->start_addr = p->ebr_addr;
    316                
    317                 l_iter = l;
    318                 while (l_iter != &(label->parts->list.head)) {
    319                         /* Checking whether EBR address makes sense. If not, we take a guess.
    320                          * So far this is simple, we just take the first preceeding sector.
    321                          * Fdisk always reserves at least 2048 sectors (1MiB), so it can have
    322                          * the EBR aligned as well as the partition itself. Parted reserves
    323                          * minimum one sector, like we do.
    324                          *
    325                          * Note that we know there is at least one sector free from previous checks.
    326                          * Also note that the user can set ebr_addr to their liking (if it's valid). */         
    327                         if (p->ebr_addr < base || p->ebr_addr >= base + ext->length ||
    328                           check_overlap(tmp, list_get_instance(l_iter, mbr_part_t, link))) {
    329                                 p->ebr_addr = p->start_addr - 1;
     282        prev_partition = partition;
     283       
     284        /*
     285         * Check EBR addresses: The code saves previous EBR
     286         * placements from other software. But if our user
     287         * modifies the logical partition chain, we have to
     288         * fix those placements if needed.
     289         */
     290       
     291        link_t *link_ebr = link;
     292        link_t *link_iter;
     293       
     294        mbr_part_t tmp_partition;
     295        tmp_partition.length = 1;
     296       
     297        while (link_ebr != &label->parts->list.head) {
     298                partition = list_get_instance(link_ebr, mbr_part_t, link);
     299               
     300                tmp_partition.start_addr = partition->ebr_addr;
     301               
     302                link_iter = link;
     303                while (link_iter != &label->parts->list.head) {
     304                        /*
     305                         * Check whether EBR address makes sense. If not, we take
     306                         * a guess.  So far this is simple, we just take the first
     307                         * preceeding sector. FDisk always reserves at least 2048
     308                         * sectors (1 MiB), so it can have the EBR aligned as well
     309                         * as the partition itself. Parted reserves minimum one
     310                         * sector, like we do.
     311                         *
     312                         * Note that we know there is at least one sector free from
     313                         * previous checks. Also note that the user can set ebr_addr
     314                         * to their liking (if it is valid).
     315                         */
     316                       
     317                        if ((partition->ebr_addr < base) ||
     318                            (partition->ebr_addr >= base + extended->length) ||
     319                            (check_overlap(&tmp_partition,
     320                            list_get_instance(link_iter, mbr_part_t, link)))) {
     321                                partition->ebr_addr = partition->start_addr - 1;
    330322                                break;
    331323                        }
    332324                       
    333                         l_iter = l_iter->next;
    334                 }
    335                
    336                 l_ebr = l_ebr->next;
    337         }
    338         mbr_free_partition(tmp);
    339        
    340         /* Encoding and writing logical partitions */
    341         while (l != &(label->parts->list.head)) {
    342                 p = list_get_instance(l, mbr_part_t, link);
    343                
    344                
    345                 encode_part(p, &(p->ebr->pte[0]), p->ebr_addr, false);
    346                 encode_part(p, &(prev_p->ebr->pte[1]), base, true);
    347                
    348                 rc = block_write_direct(dev_handle, prev_p->ebr_addr, 1, prev_p->ebr);
    349                 if (rc != EOK) {
    350                         printf(LIBMBR_NAME ": Error while writing EBR: %d - %s.\n", rc, str_error(rc));
     325                        link_iter = link_iter->next;
     326                }
     327               
     328                link_ebr = link_ebr->next;
     329        }
     330       
     331        /* Encode and write logical partitions */
     332        while (link != &label->parts->list.head) {
     333                partition = list_get_instance(link, mbr_part_t, link);
     334               
     335                encode_part(partition, &partition->ebr->pte[0],
     336                    partition->ebr_addr, false);
     337                encode_part(partition, &prev_partition->ebr->pte[1],
     338                    base, true);
     339               
     340                rc = block_write_direct(dev_handle, prev_partition->ebr_addr, 1,
     341                    prev_partition->ebr);
     342                if (rc != EOK)
    351343                        goto end;
    352                 }
    353                
    354                 prev_p = p;
    355                 l = l->next;
    356         }
    357        
    358         /* write the last EBR */
    359         encode_part(NULL, &(prev_p->ebr->pte[1]), 0, false);
    360         rc = block_write_direct(dev_handle, prev_p->ebr_addr, 1, prev_p->ebr);
    361         if (rc != EOK) {
    362                 printf(LIBMBR_NAME ": Error while writing EBR: %d - %s.\n", rc, str_error(rc));
    363                 goto end;
    364         }
    365        
    366         rc = EOK;
     344               
     345                prev_partition = partition;
     346                link = link->next;
     347        }
     348       
     349        /* Write the last EBR */
     350        encode_part(NULL, &prev_partition->ebr->pte[1], 0, false);
     351        rc = block_write_direct(dev_handle, prev_partition->ebr_addr,
     352            1, prev_partition->ebr);
    367353       
    368354end:
    369355        block_fini(dev_handle);
    370        
    371356        return rc;
    372357}
    373358
    374 /** mbr_part_t constructor */
    375 mbr_part_t * mbr_alloc_partition(void)
    376 {
    377         mbr_part_t *p = malloc(sizeof(mbr_part_t));
    378         if (p == NULL) {
     359/** Partition constructor */
     360mbr_part_t *mbr_alloc_partition(void)
     361{
     362        mbr_part_t *partition = malloc(sizeof(mbr_part_t));
     363        if (partition == NULL)
    379364                return NULL;
    380         }
    381        
    382         link_initialize(&(p->link));
    383         p->ebr = NULL;
    384         p->type = PT_UNUSED;
    385         p->status = 0;
    386         p->start_addr = 0;
    387         p->length = 0;
    388         p->ebr_addr = 0;
    389        
    390         return p;
    391 }
    392 
    393 /** mbr_partitions_t constructor */
    394 mbr_partitions_t * mbr_alloc_partitions(void)
     365       
     366        link_initialize(&partition->link);
     367        partition->ebr = NULL;
     368        partition->type = PT_UNUSED;
     369        partition->status = 0;
     370        partition->start_addr = 0;
     371        partition->length = 0;
     372        partition->ebr_addr = 0;
     373       
     374        return partition;
     375}
     376
     377/** Partitions constructor */
     378mbr_partitions_t *mbr_alloc_partitions(void)
    395379{
    396380        mbr_partitions_t *parts = malloc(sizeof(mbr_partitions_t));
    397         if (parts == NULL) {
     381        if (parts == NULL)
    398382                return NULL;
    399         }
    400        
    401         list_initialize(&(parts->list));
     383       
     384        list_initialize(&parts->list);
    402385        parts->n_primary = 0;
    403386        parts->n_logical = 0;
    404387        parts->l_extended = NULL;
    405388       
    406         /* add blank primary partitions */
    407         int i;
    408         mbr_part_t *p;
    409         for (i = 0; i < N_PRIMARY; ++i) {
    410                 p = mbr_alloc_partition();
    411                 if (p == NULL) {
     389        /* Add blank primary partitions */
     390        for (unsigned int i = 0; i < N_PRIMARY; ++i) {
     391                mbr_part_t *part = mbr_alloc_partition();
     392                if (part == NULL) {
    412393                        mbr_free_partitions(parts);
    413394                        return NULL;
    414395                }
    415                 list_append(&(p->link), &(parts->list));
    416         }
    417        
    418 
     396               
     397                list_append(&part->link, &parts->list);
     398        }
     399       
    419400        return parts;
    420401}
    421402
    422403/** Add partition
    423  *      Performs checks, sorts the list.
    424  *
    425  * @param label                 label to add to
    426  * @param p                             partition to add
    427  *
    428  * @return                              ERR_OK (0) on success, other MBR_ERR_VAL otherwise
    429  */
    430 mbr_err_val mbr_add_partition(mbr_label_t *label, mbr_part_t *p)
    431 {
    432         int rc1, rc2;
     404 *
     405 * Perform checks, sort the list.
     406 *
     407 * @param label Label to add to.
     408 * @param part  Partition to add.
     409 *
     410 * @return ERR_OK on success, other MBR_ERR_VAL otherwise
     411 *
     412 */
     413mbr_err_val mbr_add_partition(mbr_label_t *label, mbr_part_t *part)
     414{
     415        int rc = block_init(EXCHANGE_ATOMIC, label->device, 512);
     416        if ((rc != EOK) && (rc != EEXIST))
     417                return ERR_LIBBLOCK;
     418       
    433419        aoff64_t nblocks;
    434        
    435         rc1 = block_init(EXCHANGE_ATOMIC, label->device, 512);
    436         if (rc1 != EOK && rc1 != EEXIST) {
    437                 printf(LIBMBR_NAME ": Error during libblock init: %d - %s.\n", rc1, str_error(rc1));
     420        int ret = block_get_nblocks(label->device, &nblocks);
     421       
     422        if (rc != EEXIST)
     423                block_fini(label->device);
     424       
     425        if (ret != EOK)
    438426                return ERR_LIBBLOCK;
    439         }
    440        
    441         rc2 = block_get_nblocks(label->device, &nblocks);
    442        
    443         if (rc1 != EEXIST)
    444                 block_fini(label->device);
    445        
    446         if (rc2 != EOK) {
    447                 printf(LIBMBR_NAME ": Error while getting number of blocks: %d - %s.\n", rc2, str_error(rc2));
    448                 return ERR_LIBBLOCK;
    449         }
    450        
    451         if ((aoff64_t) p->start_addr + p->length > nblocks)
     427       
     428        if ((aoff64_t) part->start_addr + part->length > nblocks)
    452429                return ERR_OUT_BOUNDS;
    453430       
     
    455432                label->parts = mbr_alloc_partitions();
    456433                if (label->parts == NULL)
    457                         return ENOMEM; //FIXME! merge mbr_err_val into errno.h
    458         }
    459        
    460         if (mbr_get_flag(p, ST_LOGIC))
    461                 /* adding logical partition */
    462                 return mbr_add_logical(label, p);
     434                        // FIXME! merge mbr_err_val into errno.h
     435                        return ENOMEM;
     436        }
     437       
     438        if (mbr_get_flag(part, ST_LOGIC))
     439                return mbr_add_logical(label, part);
    463440        else
    464                 /* adding primary */
    465                 return mbr_add_primary(label, p);
     441                return mbr_add_primary(label, part);
    466442}
    467443
    468444/** Remove partition
    469  *      Removes partition by index, indexed from zero. When removing extended
    470  *  partition, all logical partitions get removed as well.
    471  *
    472  * @param label                 label to remove from
    473  * @param idx                   index of the partition to remove
    474  *
    475  * @return                              EOK on success, EINVAL if idx invalid
     445 *
     446 * Remove partition (indexed from zero). When removing the extended
     447 * partition, all logical partitions get removed as well.
     448 *
     449 * @param label Label to remove from.
     450 * @param idx   Index of the partition to remove.
     451 *
     452 * @return EOK on success.
     453 * @return EINVAL if the index is invalid.
     454 *
    476455 */
    477456int mbr_remove_partition(mbr_label_t *label, size_t idx)
    478457{
    479         link_t *l = list_nth(&(label->parts->list), idx);
    480         if (l == NULL)
     458        link_t *link = list_nth(&label->parts->list, idx);
     459        if (link == NULL)
    481460                return EINVAL;
    482461       
    483         mbr_part_t *p;
    484        
    485         /* If we're removing an extended partition, remove all logical as well */
    486         if (l == label->parts->l_extended) {
     462        /*
     463         * If removing the extended partition, remove all
     464         * logical partitions as well.
     465         */
     466        if (link == label->parts->l_extended) {
    487467                label->parts->l_extended = NULL;
    488468               
    489                 link_t *it = l->next;
    490                 link_t *next_it;
    491                 while (it != &(label->parts->list.head)) {
    492                         next_it = it->next;
     469                link_t *iterator = link->next;
     470                link_t *next;
     471               
     472                while (iterator != &label->parts->list.head) {
     473                        next = iterator->next;
     474                        mbr_part_t *partition =
     475                            list_get_instance(iterator, mbr_part_t, link);
    493476                       
    494                         p = list_get_instance(it, mbr_part_t, link);
    495                         if (mbr_get_flag(p, ST_LOGIC)) {
    496                                 list_remove(it);
    497                                 label->parts->n_logical -= 1;
    498                                 mbr_free_partition(p);
     477                        if (mbr_get_flag(partition, ST_LOGIC)) {
     478                                list_remove(iterator);
     479                                label->parts->n_logical--;
     480                                mbr_free_partition(partition);
    499481                        }
    500482                       
    501                         it = next_it;
    502                 }
    503                
     483                        iterator = next;
     484                }
    504485        }
    505486       
    506487        /* Remove the partition itself */
    507         p = list_get_instance(l, mbr_part_t, link);
    508         if (mbr_get_flag(p, ST_LOGIC)) {
    509                 label->parts->n_logical -= 1;
    510                 list_remove(l);
    511                 mbr_free_partition(p);
     488        mbr_part_t *partition =
     489            list_get_instance(link, mbr_part_t, link);
     490       
     491        if (mbr_get_flag(partition, ST_LOGIC)) {
     492                label->parts->n_logical--;
     493                list_remove(link);
     494                mbr_free_partition(partition);
    512495        } else {
    513                 /* Cannot remove primary - it would break ordering, just zero it */
    514                 label->parts->n_primary -= 1;
    515                 p->type = 0;
    516                 p->status = 0;
    517                 p->start_addr = 0;
    518                 p->length = 0;
    519                 p->ebr_addr = 0;
     496                /*
     497                 * Cannot remove a primary partition without
     498                 * breaking the ordering. Just zero it.
     499                 */
     500                label->parts->n_primary--;
     501                partition->type = 0;
     502                partition->status = 0;
     503                partition->start_addr = 0;
     504                partition->length = 0;
     505                partition->ebr_addr = 0;
    520506        }
    521507       
     
    523509}
    524510
    525 /** mbr_part_t destructor */
    526 void mbr_free_partition(mbr_part_t *p)
    527 {
    528         if (p->ebr != NULL)
    529                 free(p->ebr);
    530         free(p);
    531 }
    532 
    533 /** Get flag bool value */
    534 int mbr_get_flag(mbr_part_t *p, MBR_FLAGS flag)
    535 {
    536         return (p->status & (1 << flag)) ? 1 : 0;
    537 }
    538 
    539 /** Set a specifig status flag to a value */
    540 void mbr_set_flag(mbr_part_t *p, MBR_FLAGS flag, bool value)
    541 {
    542         uint16_t status = p->status;
    543 
    544         if (value)
    545                 status = status | (1 << flag);
     511/** Partition destructor */
     512void mbr_free_partition(mbr_part_t *partition)
     513{
     514        if (partition->ebr != NULL)
     515                free(partition->ebr);
     516       
     517        free(partition);
     518}
     519
     520/** Check for flag */
     521int mbr_get_flag(mbr_part_t *partition, mbr_flags_t flag)
     522{
     523        return (partition->status & (1 << flag));
     524}
     525
     526/** Set a specific status flag */
     527void mbr_set_flag(mbr_part_t *partition, mbr_flags_t flag, bool set)
     528{
     529        if (set)
     530                partition->status |= 1 << flag;
    546531        else
    547                 status = status ^ (status & (1 << flag));
    548 
    549         p->status = status;
     532                partition->status &= ~((uint16_t) (1 << flag));
    550533}
    551534
     
    553536uint32_t mbr_get_next_aligned(uint32_t addr, unsigned int alignment)
    554537{
    555         uint32_t div = addr / alignment;
    556         return (div + 1) * alignment;
    557 }
    558 
    559 list_t * mbr_get_list(mbr_label_t *label)
     538        return ALIGN_UP(addr + 1, alignment);
     539}
     540
     541list_t *mbr_get_list(mbr_label_t *label)
    560542{
    561543        if (label->parts != NULL)
    562                 return &(label->parts->list);
     544                return &label->parts->list;
    563545        else
    564546                return NULL;
    565547}
    566548
    567 mbr_part_t * mbr_get_first_partition(mbr_label_t *label)
     549mbr_part_t *mbr_get_first_partition(mbr_label_t *label)
    568550{
    569551        list_t *list = mbr_get_list(label);
    570         if (list != NULL && !list_empty(list))
     552        if ((list != NULL) && (!list_empty(list)))
    571553                return list_get_instance(list->head.next, mbr_part_t, link);
    572554        else
     
    574556}
    575557
    576 mbr_part_t * mbr_get_next_partition(mbr_label_t *label, mbr_part_t *p)
     558mbr_part_t *mbr_get_next_partition(mbr_label_t *label, mbr_part_t *partition)
    577559{
    578560        list_t *list = mbr_get_list(label);
    579         if (list != NULL && &(p->link) != list_last(list))
    580                 return list_get_instance(p->link.next, mbr_part_t, link);
     561        if ((list != NULL) && (&partition->link != list_last(list)))
     562                return list_get_instance(partition->link.next, mbr_part_t, link);
    581563        else
    582564                return NULL;
    583565}
    584566
    585 /** Just a wrapper for free() */
    586567void mbr_free_mbr(mbr_t *mbr)
    587568{
     
    591572/** Free partition list
    592573 *
    593  * @param parts         partition list to be freed
     574 * @param parts Partition list to be freed
     575 *
    594576 */
    595577void mbr_free_partitions(mbr_partitions_t *parts)
    596578{
    597579        list_foreach_safe(parts->list, cur_link, next) {
    598                 mbr_part_t *p = list_get_instance(cur_link, mbr_part_t, link);
     580                mbr_part_t *partition = list_get_instance(cur_link, mbr_part_t, link);
    599581                list_remove(cur_link);
    600                 mbr_free_partition(p);
    601         }
    602 
     582                mbr_free_partition(partition);
     583        }
     584       
    603585        free(parts);
    604586}
    605587
    606 /* Internal functions follow */
    607 
    608 static br_block_t *alloc_br()
     588static br_block_t *alloc_br(void)
    609589{
    610590        br_block_t *br = malloc(sizeof(br_block_t));
     
    618598}
    619599
    620 /** Parse partition entry to mbr_part_t
    621  * @return              returns 1, if extended partition, 0 otherwise
    622  * */
    623 static int decode_part(pt_entry_t *src, mbr_part_t *trgt, uint32_t base)
    624 {
    625         trgt->type = src->ptype;
    626 
    627         trgt->status = (trgt->status & 0xFF00) | (uint16_t) src->status;
    628 
    629         trgt->start_addr = uint32_t_le2host(src->first_lba) + base;
    630         trgt->length = uint32_t_le2host(src->length);
    631 
    632         return (src->ptype == PT_EXTENDED) ? 1 : 0;
    633 }
    634 
    635 /** Parse MBR contents to mbr_part_t list */
    636 static int decode_logical(mbr_label_t *label, mbr_part_t * ext)
    637 {
    638         int rc;
    639         mbr_part_t *p;
    640 
    641         if (ext == NULL)
     600/** Decode partition entry */
     601static int decode_part(pt_entry_t *src, mbr_part_t *partition, uint32_t base)
     602{
     603        partition->type = src->ptype;
     604        partition->status = (partition->status & 0xff00) | (uint16_t) src->status;
     605        partition->start_addr = uint32_t_le2host(src->first_lba) + base;
     606        partition->length = uint32_t_le2host(src->length);
     607       
     608        return (src->ptype == PT_EXTENDED);
     609}
     610
     611/** Parse logical partitions */
     612static int decode_logical(mbr_label_t *label, mbr_part_t *extended)
     613{
     614        if (extended == NULL)
    642615                return EOK;
    643 
    644         uint32_t base = ext->start_addr;
     616       
     617        br_block_t *ebr = alloc_br();
     618        if (ebr == NULL)
     619                return ENOMEM;
     620       
     621        uint32_t base = extended->start_addr;
    645622        uint32_t addr = base;
    646         br_block_t *ebr;
    647        
    648         rc = block_init(EXCHANGE_ATOMIC, label->device, 512);
     623       
     624        int rc = block_init(EXCHANGE_ATOMIC, label->device, 512);
    649625        if (rc != EOK)
    650                 return rc;
    651        
    652         ebr = alloc_br();
    653         if (ebr == NULL) {
     626                goto end;
     627       
     628        rc = block_read_direct(label->device, addr, 1, ebr);
     629        if (rc != EOK)
     630                goto end;
     631       
     632        if (uint16_t_le2host(ebr->signature) != BR_SIGNATURE) {
     633                rc = EINVAL;
     634                goto end;
     635        }
     636       
     637        if (ebr->pte[0].ptype == PT_UNUSED) {
     638                rc = EOK;
     639                goto end;
     640        }
     641       
     642        mbr_part_t *partition = mbr_alloc_partition();
     643        if (partition == NULL) {
    654644                rc = ENOMEM;
    655645                goto end;
    656646        }
    657647       
    658         rc = block_read_direct(label->device, addr, 1, ebr);
    659         if (rc != EOK) {
    660                 goto free_ebr_end;
    661         }
    662        
    663         if (uint16_t_le2host(ebr->signature) != BR_SIGNATURE) {
    664                 rc = EINVAL;
    665                 goto free_ebr_end;
    666         }
    667        
    668         if (ebr->pte[0].ptype == PT_UNUSED) {
    669                 rc = EOK;
    670                 goto free_ebr_end;
    671         }
    672        
    673         p = mbr_alloc_partition();
    674         if (p == NULL) {
    675                 rc = ENOMEM;
    676                 goto free_ebr_end;
    677         }
    678        
    679         decode_part(&(ebr->pte[0]), p, base);
    680         mbr_set_flag(p, ST_LOGIC, true);
    681         p->ebr = ebr;
    682         p->ebr_addr = addr;
    683         rc = mbr_add_partition(label, p);
    684         if (rc != ERR_OK)
    685                 return EINVAL;
     648        decode_part(&ebr->pte[0], partition, base);
     649        mbr_set_flag(partition, ST_LOGIC, true);
     650        partition->ebr = ebr;
     651        partition->ebr_addr = addr;
     652       
     653        rc = mbr_add_partition(label, partition);
     654        if (rc != ERR_OK)
     655                goto end;
    686656       
    687657        addr = uint32_t_le2host(ebr->pte[1].first_lba) + base;
    688658       
    689659        while (ebr->pte[1].ptype != PT_UNUSED) {
    690                
    691                 ebr = alloc_br();
    692                 if (ebr == NULL) {
     660                rc = block_read_direct(label->device, addr, 1, ebr);
     661                if (rc != EOK)
     662                        goto end;
     663               
     664                if (uint16_t_le2host(ebr->signature) != BR_SIGNATURE) {
     665                        rc = EINVAL;
     666                        goto end;
     667                }
     668               
     669                mbr_part_t *partition = mbr_alloc_partition();
     670                if (partition == NULL) {
    693671                        rc = ENOMEM;
    694672                        goto end;
    695673                }
    696674               
    697                 rc = block_read_direct(label->device, addr, 1, ebr);
    698                 if (rc != EOK) {
    699                         goto free_ebr_end;
    700                 }
    701                
    702                 if (uint16_t_le2host(ebr->signature) != BR_SIGNATURE) {
    703                         rc = EINVAL;
    704                         goto free_ebr_end;
    705                 }
    706                
    707                 p = mbr_alloc_partition();
    708                 if (p == NULL) {
    709                         rc = ENOMEM;
    710                         goto free_ebr_end;
    711                 }
    712                
    713                 decode_part(&(ebr->pte[0]), p, addr);
    714                 mbr_set_flag(p, ST_LOGIC, true);
    715                 p->ebr = ebr;
    716                 p->ebr_addr = addr;
    717                 rc = mbr_add_partition(label, p);
     675                decode_part(&ebr->pte[0], partition, addr);
     676                mbr_set_flag(partition, ST_LOGIC, true);
     677                partition->ebr = ebr;
     678                partition->ebr_addr = addr;
     679               
     680                rc = mbr_add_partition(label, partition);
    718681                if (rc != ERR_OK)
    719                         return EINVAL;
     682                        goto end;
    720683               
    721684                addr = uint32_t_le2host(ebr->pte[1].first_lba) + base;
     
    723686       
    724687        rc = EOK;
    725         goto end;
    726        
    727 free_ebr_end:
    728         free(ebr);
    729688       
    730689end:
     690        // FIXME possible memory leaks
    731691        block_fini(label->device);
    732692       
     
    734694}
    735695
    736 /** Convert mbr_part_t to pt_entry_t */
    737 static void encode_part(mbr_part_t * src, pt_entry_t * trgt, uint32_t base, bool ebr)
     696/** Encode partition entry */
     697static void encode_part(mbr_part_t *src, pt_entry_t *entry, uint32_t base,
     698    bool ebr)
    738699{
    739700        if (src != NULL) {
    740                 trgt->status = (uint8_t) (src->status & 0xFF);
    741                 /* ingoring CHS */
    742                 trgt->first_chs[0] = 0xFE;
    743                 trgt->first_chs[1] = 0xFF;
    744                 trgt->first_chs[2] = 0xFF;
    745                 trgt->last_chs[0] = 0xFE;
    746                 trgt->last_chs[1] = 0xFF;
    747                 trgt->last_chs[2] = 0xFF;
    748                 if (ebr) {      /* encoding reference to EBR */
    749                         trgt->ptype = PT_EXTENDED_LBA;
    750                         trgt->first_lba = host2uint32_t_le(src->ebr_addr - base);
    751                         trgt->length = host2uint32_t_le(src->length + src->start_addr - src->ebr_addr);
    752                 } else {        /* encoding reference to partition */
    753                         trgt->ptype = src->type;
    754                         trgt->first_lba = host2uint32_t_le(src->start_addr - base);
    755                         trgt->length = host2uint32_t_le(src->length);
    756                 }
    757                
    758                 if (trgt->ptype == PT_UNUSED)
    759                         memset(trgt, 0, sizeof(pt_entry_t));
    760         } else {
    761                 memset(trgt, 0, sizeof(pt_entry_t));
    762         }
    763 }
    764 
    765 /** Check whether two partitions overlap
    766  *
    767  * @return              true/false
    768  */
    769 static bool check_overlap(mbr_part_t * p1, mbr_part_t * p2)
    770 {
    771         if (p1->start_addr < p2->start_addr && p1->start_addr + p1->length <= p2->start_addr) {
     701                entry->status = (uint8_t) src->status & 0xff;
     702               
     703                /* Ignore CHS */
     704                entry->first_chs[0] = 0xfe;
     705                entry->first_chs[1] = 0xff;
     706                entry->first_chs[2] = 0xff;
     707                entry->last_chs[0] = 0xfe;
     708                entry->last_chs[1] = 0xff;
     709                entry->last_chs[2] = 0xff;
     710               
     711                if (ebr) {
     712                        /* Encode reference to EBR */
     713                        entry->ptype = PT_EXTENDED_LBA;
     714                        entry->first_lba = host2uint32_t_le(src->ebr_addr - base);
     715                        entry->length = host2uint32_t_le(src->length + src->start_addr -
     716                            src->ebr_addr);
     717                } else {
     718                        /* Encode reference to partition */
     719                        entry->ptype = src->type;
     720                        entry->first_lba = host2uint32_t_le(src->start_addr - base);
     721                        entry->length = host2uint32_t_le(src->length);
     722                }
     723               
     724                if (entry->ptype == PT_UNUSED)
     725                        memset(entry, 0, sizeof(pt_entry_t));
     726        } else
     727                memset(entry, 0, sizeof(pt_entry_t));
     728}
     729
     730/** Check whether two partitions overlap */
     731static bool check_overlap(mbr_part_t *part1, mbr_part_t *part2)
     732{
     733        if ((part1->start_addr < part2->start_addr) &&
     734            (part1->start_addr + part1->length <= part2->start_addr))
    772735                return false;
    773         } else if (p1->start_addr > p2->start_addr && p2->start_addr + p2->length <= p1->start_addr) {
     736       
     737        if ((part1->start_addr > part2->start_addr) &&
     738            (part2->start_addr + part2->length <= part1->start_addr))
    774739                return false;
    775         }
    776 
     740       
    777741        return true;
    778742}
    779743
    780 /** Check whether one partition encapsulates the other
    781  *
    782  * @return              true/false
    783  */
    784 static bool check_encaps(mbr_part_t * inner, mbr_part_t * outer)
    785 {
    786         if (inner->start_addr <= outer->start_addr || outer->start_addr + outer->length <= inner->start_addr) {
     744/** Check whether one partition encapsulates the other */
     745static bool check_encaps(mbr_part_t *inner, mbr_part_t *outer)
     746{
     747        if ((inner->start_addr <= outer->start_addr) ||
     748            (outer->start_addr + outer->length <= inner->start_addr))
    787749                return false;
    788         } else if (outer->start_addr + outer->length < inner->start_addr + inner->length) {
     750       
     751        if (outer->start_addr + outer->length < inner->start_addr + inner->length)
    789752                return false;
    790         }
    791 
     753       
    792754        return true;
    793755}
    794756
    795 /** Check whether one partition preceeds the other
    796  *
    797  * @return              true/false
    798  */
    799 static bool check_preceeds(mbr_part_t * preceeder, mbr_part_t * precedee)
     757/** Check whether one partition preceeds the other */
     758static bool check_preceeds(mbr_part_t *preceeder, mbr_part_t *precedee)
    800759{
    801760        return preceeder->start_addr < precedee->start_addr;
    802761}
    803762
    804 mbr_err_val mbr_add_primary(mbr_label_t *label, mbr_part_t *p)
    805 {
    806         if (label->parts->n_primary == 4) {
     763mbr_err_val mbr_add_primary(mbr_label_t *label, mbr_part_t *part)
     764{
     765        if (label->parts->n_primary == 4)
    807766                return ERR_PRIMARY_FULL;
    808         }
    809        
    810         /* Check if partition makes space for MBR itself. */
    811         if (p->start_addr == 0) {
     767       
     768        /* Check if partition makes space for MBR itself */
     769        if (part->start_addr == 0)
    812770                return ERR_OUT_BOUNDS;
    813         }
    814        
    815         /* if it's extended, is there any other one? */
    816         if ((p->type == PT_EXTENDED || p->type == PT_EXTENDED_LBA) && label->parts->l_extended != NULL) {
     771       
     772        /* If it is an extended partition, is there any other one? */
     773        if (((part->type == PT_EXTENDED) || (part->type == PT_EXTENDED_LBA)) &&
     774            (label->parts->l_extended != NULL))
    817775                return ERR_EXTENDED_PRESENT;
    818         }
    819        
    820         /* find a place and add it */
     776       
     777        /* Find a place and add it */
    821778        mbr_part_t *iter;
    822779        mbr_part_t *empty = NULL;
     
    825782                        if (empty == NULL)
    826783                                empty = iter;
    827                 } else if (check_overlap(p, iter))
     784                } else if (check_overlap(part, iter))
    828785                        return ERR_OVERLAP;
    829786        }
    830787       
    831         list_insert_after(&(p->link), &(empty->link));
    832         list_remove(&(empty->link));
     788        list_insert_after(&part->link, &empty->link);
     789        list_remove(&empty->link);
    833790        free(empty);
    834791       
    835         label->parts->n_primary += 1;
    836        
    837         if (p->type == PT_EXTENDED || p->type == PT_EXTENDED_LBA)
    838                 label->parts->l_extended = &(p->link);
     792        label->parts->n_primary++;
     793       
     794        if ((part->type == PT_EXTENDED) || (part->type == PT_EXTENDED_LBA))
     795                label->parts->l_extended = &part->link;
    839796       
    840797        return EOK;
    841798}
    842799
    843 mbr_err_val mbr_add_logical(mbr_label_t *label, mbr_part_t *p)
    844 {
    845         /* is there any extended partition? */
     800mbr_err_val mbr_add_logical(mbr_label_t *label, mbr_part_t *part)
     801{
     802        /* Is there any extended partition? */
    846803        if (label->parts->l_extended == NULL)
    847804                return ERR_NO_EXTENDED;
    848805       
    849         /* is the logical partition inside the extended one? */
    850         mbr_part_t *ext = list_get_instance(label->parts->l_extended, mbr_part_t, link);
    851         if (!check_encaps(p, ext))
     806        /* Is the logical partition inside the extended partition? */
     807        mbr_part_t *extended = list_get_instance(label->parts->l_extended, mbr_part_t, link);
     808        if (!check_encaps(part, extended))
    852809                return ERR_OUT_BOUNDS;
    853810       
    854         /* find a place for the new partition in a sorted linked list */
     811        /* Find a place for the new partition in a sorted linked list */
    855812        bool first_logical = true;
    856813        mbr_part_t *iter;
    857814        mbr_part_foreach (label, iter) {
    858815                if (mbr_get_flag(iter, ST_LOGIC)) {
    859                         if (check_overlap(p, iter))
     816                        if (check_overlap(part, iter))
    860817                                return ERR_OVERLAP;
    861                         if (check_preceeds(iter, p)) {
    862                                 /* checking if there's at least one sector of space preceeding */
    863                                 if ((iter->start_addr + iter->length) >= p->start_addr - 1)
     818                       
     819                        if (check_preceeds(iter, part)) {
     820                                /* Check if there is at least one sector of space preceeding */
     821                                if ((iter->start_addr + iter->length) >= part->start_addr - 1)
    864822                                        return ERR_NO_EBR;
    865                         } else if (first_logical){
    866                                 /* First logical partition's EBR is before every other
    867                                  * logical partition. Thus we don't check if this partition
    868                                  * leaves enough space for it. */
     823                        } else if (first_logical) {
     824                                /*
     825                                 * First logical partition's EBR is before every other
     826                                 * logical partition. Thus we do not check if this partition
     827                                 * leaves enough space for it.
     828                                 */
    869829                                first_logical = false;
    870830                        } else {
    871                                 /* checking if there's at least one sector of space following (for following partitions's EBR) */
    872                                 if ((p->start_addr + p->length) >= iter->start_addr - 1)
     831                                /*
     832                                 * Check if there is at least one sector of space following
     833                                 * (for following partitions's EBR).
     834                                 */
     835                                if ((part->start_addr + part->length) >= iter->start_addr - 1)
    873836                                        return ERR_NO_EBR;
    874837                        }
     
    876839        }
    877840       
    878         /* alloc EBR if it's not already there */
    879         if (p->ebr == NULL) {
    880                 p->ebr = alloc_br();
    881                 if (p->ebr == NULL) {
     841        /* Allocate EBR if it is not already there */
     842        if (part->ebr == NULL) {
     843                part->ebr = alloc_br();
     844                if (part->ebr == NULL)
    882845                        return ERR_NOMEM;
    883                 }
    884         }
    885        
    886         /* add it */
    887         list_append(&(p->link), &(label->parts->list));
    888         label->parts->n_logical += 1;
     846        }
     847       
     848        list_append(&part->link, &label->parts->list);
     849        label->parts->n_logical++;
    889850       
    890851        return EOK;
    891852}
    892 
    893 
    894 
  • uspace/lib/mbr/libmbr.h

    rd51beba3 r6453e306  
    11/*
    22 * Copyright (c) 2009 Jiri Svoboda
    3  * Copyright (c) 2011, 2012, 2013 Dominik Taborsky
     3 * Copyright (c) 2011-2013 Dominik Taborsky
    44 * All rights reserved.
    55 *
     
    2828 */
    2929
    30  /** @addtogroup libmbr
     30/** @addtogroup libmbr
    3131 * @{
    3232 */
     
    4040#include "mbr.h"
    4141
    42 #define LIBMBR_NAME     "libmbr"
     42/*
     43 * WARNING: When changing both header and partitions, write first header,
     44 * then partitions. The MBR headers' raw_data is not updated to follow
     45 * partition changes.
     46 *
     47 * NOTE: Writing partitions writes the complete header as well.
     48 */
    4349
    4450typedef enum {
     
    4854        /** Logical partition, 0 = primary, 1 = logical*/
    4955        ST_LOGIC = 8
    50 } MBR_FLAGS;
     56} mbr_flags_t;
    5157
    5258typedef enum {
     
    7783} mbr_t;
    7884
    79 
    8085/** Partition */
    8186typedef struct mbr_part {
     
    9196        uint32_t length;
    9297        /** Points to Extended Boot Record of logical partition */
    93         br_block_t * ebr;
     98        br_block_t *ebr;
    9499        /** EBR address */
    95100        uint32_t ebr_addr;
     
    101106        unsigned char n_primary;
    102107        /** Index to the extended partition in the array */
    103         link_t * l_extended;
     108        link_t *l_extended;
    104109        /** Number of logical partitions */
    105110        unsigned int n_logical;
     
    111116typedef struct mbr_label {
    112117        /** MBR header */
    113         mbr_t * mbr;
     118        mbr_t *mbr;
    114119        /** Partition list */
    115120        mbr_partitions_t * parts;
     
    118123} mbr_label_t;
    119124
    120 /* Alloc complete label structure */
    121 extern mbr_label_t * mbr_alloc_label(void);
     125#define mbr_part_foreach(label, iterator) \
     126        for (iterator = list_get_instance((label)->parts->list.head.next, mbr_part_t, link); \
     127            iterator != list_get_instance(&((label)->parts->list.head), mbr_part_t, link); \
     128            iterator = list_get_instance(iterator->link.next, mbr_part_t, link))
     129
     130extern mbr_label_t *mbr_alloc_label(void);
     131
    122132extern void mbr_set_device(mbr_label_t *, service_id_t);
    123 
    124 /* Read/Write MBR header.
    125  * WARNING: when changing both header and partitions, write first header,
    126  * then partitions. The MBR headers' raw_data is NOT updated to follow
    127  * partition changes. */
    128 extern mbr_t * mbr_alloc_mbr(void);
     133extern mbr_t *mbr_alloc_mbr(void);
    129134extern int mbr_read_mbr(mbr_label_t *, service_id_t);
    130135extern int mbr_write_mbr(mbr_label_t *, service_id_t);
    131136extern int mbr_is_mbr(mbr_label_t *);
    132137
    133 /* Read/Write/Set MBR partitions.
    134  * NOTE: Writing partitions writes the complete header as well. */
    135 extern int          mbr_read_partitions(mbr_label_t *);
    136 extern int          mbr_write_partitions(mbr_label_t *, service_id_t);
    137 extern mbr_part_t * mbr_alloc_partition(void);
    138 extern mbr_partitions_t * mbr_alloc_partitions(void);
    139 extern mbr_err_val  mbr_add_partition(mbr_label_t *, mbr_part_t *);
    140 extern int          mbr_remove_partition(mbr_label_t *, size_t);
    141 extern int          mbr_get_flag(mbr_part_t *, MBR_FLAGS);
    142 extern void         mbr_set_flag(mbr_part_t *, MBR_FLAGS, bool);
    143 extern uint32_t     mbr_get_next_aligned(uint32_t, unsigned int);
    144 extern list_t *     mbr_get_list(mbr_label_t *);
    145 extern mbr_part_t * mbr_get_first_partition(mbr_label_t *);
    146 extern mbr_part_t * mbr_get_next_partition(mbr_label_t *, mbr_part_t *);
     138extern int mbr_read_partitions(mbr_label_t *);
     139extern int mbr_write_partitions(mbr_label_t *, service_id_t);
     140extern mbr_part_t *mbr_alloc_partition(void);
     141extern mbr_partitions_t *mbr_alloc_partitions(void);
     142extern mbr_err_val mbr_add_partition(mbr_label_t *, mbr_part_t *);
     143extern int mbr_remove_partition(mbr_label_t *, size_t);
     144extern int mbr_get_flag(mbr_part_t *, mbr_flags_t);
     145extern void mbr_set_flag(mbr_part_t *, mbr_flags_t, bool);
     146extern uint32_t mbr_get_next_aligned(uint32_t, unsigned int);
     147extern list_t *mbr_get_list(mbr_label_t *);
     148extern mbr_part_t *mbr_get_first_partition(mbr_label_t *);
     149extern mbr_part_t *mbr_get_next_partition(mbr_label_t *, mbr_part_t *);
    147150
    148 #define mbr_part_foreach(label, iterator) \
    149         for (iterator  = list_get_instance((label)->parts->list.head.next, mbr_part_t, link); \
    150              iterator != list_get_instance(&((label)->parts->list.head), mbr_part_t, link); \
    151              iterator  = list_get_instance(iterator->link.next, mbr_part_t, link))
    152 
    153 
    154 /* free() wrapper functions. */
    155151extern void mbr_free_label(mbr_label_t *);
    156152extern void mbr_free_mbr(mbr_t *);
     
    159155
    160156#endif
    161 
  • uspace/lib/mbr/mbr.h

    rd51beba3 r6453e306  
    11/*
    22 * Copyright (c) 2009 Jiri Svoboda
    3  * Copyright (c) 2011, 2012, 2013 Dominik Taborsky
     3 * Copyright (c) 2011-2013 Dominik Taborsky
    44 * All rights reserved.
    55 *
     
    3939#include <sys/types.h>
    4040
    41 /** Number of primary partition records */
    42 #define N_PRIMARY               4
    43 
    44 /** Boot record signature */
    45 #define BR_SIGNATURE    0xAA55
     41enum {
     42        /** Number of primary partition records */
     43        N_PRIMARY = 4,
     44       
     45        /** Boot record signature */
     46        BR_SIGNATURE = 0xAA55
     47};
    4648
    4749enum {
     
    5557enum {
    5658        /** Unused partition entry */
    57         PT_UNUSED       = 0x00,
     59        PT_UNUSED = 0x00,
    5860        /** Extended partition */
    59         PT_EXTENDED     = 0x05,
     61        PT_EXTENDED = 0x05,
    6062        /** Extended partition with LBA */
    61         PT_EXTENDED_LBA = 0x0F,
     63        PT_EXTENDED_LBA = 0x0F,
    6264        /** GPT Protective partition */
    63         PT_GPT  = 0xEE,
     65        PT_GPT = 0xEE,
    6466};
    6567
Note: See TracChangeset for help on using the changeset viewer.