Changeset 6453e306 in mainline for uspace/lib/mbr/libmbr.c


Ignore:
Timestamp:
2013-12-25T16:09:43Z (10 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

File:
1 edited

Legend:

Unmodified
Added
Removed
  • 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 
Note: See TracChangeset for help on using the changeset viewer.