Changeset 6453e306 in mainline for uspace/lib/gpt


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/gpt
Files:
4 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 
Note: See TracChangeset for help on using the changeset viewer.