Ignore:
File:
1 edited

Legend:

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

    r9bdfde73 r44c4886  
    5151#include "libgpt.h"
    5252
    53 static int load_and_check_header(service_id_t handle, aoff64_t addr, size_t b_size, gpt_header_t *header);
     53static int load_and_check_header(service_id_t handle, aoff64_t addr, size_t b_size, gpt_header_t * header);
    5454static gpt_partitions_t * alloc_part_array(uint32_t num);
    55 static int extend_part_array(gpt_partitions_t *);
    56 static int reduce_part_array(gpt_partitions_t *);
     55static int extend_part_array(gpt_partitions_t * p);
     56static int reduce_part_array(gpt_partitions_t * p);
    5757static long long nearest_larger_int(double a);
    58 static uint8_t get_byte(const char *);
    59 static int check_overlap(gpt_part_t * p1, gpt_part_t * p2);
     58
    6059
    6160/** Allocate memory for gpt label */
     
    180179
    181180        rc = block_init(EXCHANGE_ATOMIC, dev_handle, b_size);
    182         if (rc != EOK && rc != EEXIST)
     181        if (rc != EOK)
    183182                return rc;
    184183
     
    291290
    292291/** Write GPT and partitions to device
    293  * Note: also writes the header.
    294292 * @param label        label to write
    295293 * @param dev_handle   device to write the data to
     
    302300        size_t b_size;
    303301        uint32_t e_size = uint32_t_le2host(label->gpt->header->entry_size);
    304         size_t fill = label->parts->fill > GPT_MIN_PART_NUM ? label->parts->fill : GPT_MIN_PART_NUM;
    305        
     302
    306303        label->gpt->header->pe_array_crc32 = compute_crc32(
    307304                                       (uint8_t *) label->parts->part_array,
    308                                        fill * e_size);
     305                                       label->parts->fill * e_size);
    309306       
    310307        /* comm_size of 4096 is ignored */
    311308        rc = block_init(EXCHANGE_ATOMIC, dev_handle, 4096);
    312         if (rc != EOK && rc != EEXIST)
    313                 return rc;
    314        
     309        if (rc != EOK)
     310                return rc;
     311
    315312        rc = block_get_bsize(dev_handle, &b_size);
    316313        if (rc != EOK)
    317314                goto fail;
    318        
    319         aoff64_t n_blocks;
    320         rc = block_get_nblocks(dev_handle, &n_blocks);
    321         if (rc != EOK)
    322                 goto fail;
    323        
    324         /* Write to backup GPT partition array location */
    325         //rc = block_write_direct(dev_handle, n_blocks - 1, GPT_HDR_BS, header->raw_data);
    326         if (rc != EOK)
    327                 goto fail;
    328        
     315
    329316        /* Write to main GPT partition array location */
    330317        rc = block_write_direct(dev_handle, uint64_t_le2host(label->gpt->header->entry_lba),
     
    333320        if (rc != EOK)
    334321                goto fail;
    335        
     322
     323        aoff64_t n_blocks;
     324        rc = block_get_nblocks(dev_handle, &n_blocks);
     325        if (rc != EOK)
     326                goto fail;
     327
     328        /* Write to backup GPT partition array location */
     329        //rc = block_write_direct(dev_handle, n_blocks - 1, GPT_HDR_BS, header->raw_data);
     330        block_fini(dev_handle);
     331        if (rc != EOK)
     332                goto fail;
     333
     334
    336335        return gpt_write_header(label, dev_handle);
    337336       
     
    348347 * This returns a memory block (zero-filled) and needs gpt_add_partition()
    349348 * to be called to insert it into a partition array.
    350  * Requires you to call gpt_free_partition afterwards.
     349 * Requires you to call gpt_free_partition after use.
    351350 */
    352351gpt_part_t * gpt_alloc_partition(void)
     
    368367 *
    369368 * Note: use either gpt_alloc_partition or gpt_get_partition.
    370  * This one returns a pointer to the first empty structure already
    371  * inside the array, so don't call gpt_add_partition() afterwards.
     369 * This one return a pointer to a structure already inside the array, so
     370 * there's no need to call gpt_add_partition().
    372371 * This is the one you will usually want.
    373372 */
    374373gpt_part_t * gpt_get_partition(gpt_label_t *label)
    375374{
    376         gpt_part_t *p;
    377        
    378         /* Find the first empty entry */
    379         do {
    380                 if (label->parts->fill == label->parts->arr_size) {
    381                         if (extend_part_array(label->parts) == -1)
    382                                 return NULL;
    383                 }
    384                
    385                 p = label->parts->part_array + label->parts->fill++;
    386                
    387         } while (gpt_get_part_type(p) != GPT_PTE_UNUSED);
    388        
    389         return p;
    390 }
    391 
    392 /** Get partition already inside the label
    393  *
    394  * @param label   label to carrying the partition
    395  * @param idx     index of the partition
    396  *
    397  * @return        returns pointer to the partition
    398  *                or NULL when out of range
    399  *
    400  * Note: For new partitions use either gpt_alloc_partition or
    401  * gpt_get_partition unless you want a partition at a specific place.
    402  * This returns a pointer to a structure already inside the array,
    403  * so don't call gpt_add_partition() afterwards.
    404  * This function is handy when you want to change already existing
    405  * partition or to simply write somewhere in the middle. This works only
    406  * for indexes smaller than either 128 or the actual number of filled
    407  * entries.
    408  */
    409 gpt_part_t * gpt_get_partition_at(gpt_label_t *label, size_t idx)
    410 {
    411         return NULL;
    412        
    413         if (idx >= GPT_MIN_PART_NUM && idx >= label->parts->fill)
    414                 return NULL;
    415        
    416         return label->parts->part_array + idx;
     375        if (label->parts->fill == label->parts->arr_size) {
     376                if (extend_part_array(label->parts) == -1)
     377                        return NULL;
     378        }
     379
     380        return label->parts->part_array + label->parts->fill++;
    417381}
    418382
     
    426390 * Note: for use with gpt_alloc_partition() only. You will get
    427391 * duplicates with gpt_get_partition().
    428  * Note: does not call gpt_free_partition()!
    429392 */
    430393int gpt_add_partition(gpt_label_t *label, gpt_part_t *partition)
     
    435398        }
    436399       
    437         /*FIXME:
    438          * Check dimensions and stuff! */
    439         gpt_part_foreach(label, p) {
    440                 if (gpt_get_part_type(p) != GPT_PTE_UNUSED) {
    441                         if (check_overlap(partition, p))
    442                                 return EINVAL;
    443                 }
    444         }
    445        
    446400        memcpy(label->parts->part_array + label->parts->fill++,
    447401               partition, sizeof(gpt_part_t));
    448        
    449        
    450402       
    451403        return EOK;
     
    463415int gpt_remove_partition(gpt_label_t *label, size_t idx)
    464416{
    465         if (idx >= label->parts->fill)
    466                 return EINVAL;
    467        
    468         /* FIXME!
    469          * If we allow blank spots, we break the array. If we have more than
    470          * 128 partitions in the array and then remove something from
    471          * the first 128 partitions, we would forget to write the last one.*/
    472         memset(label->parts->part_array + idx, 0, sizeof(gpt_entry_t));
    473        
    474         label->parts->fill -= 1;
    475        
    476         /* FIXME! HOPEFULLY FIXED.
    477          * We cannot reduce the array so simply. We may have some partitions
    478          * there since we allow blank spots. */
    479         gpt_part_t * p;
     417        if (idx != label->parts->fill - 1) {
     418                memmove(label->parts->part_array + idx,
     419                        label->parts->part_array + idx + 1,
     420                        (label->parts->fill - 1) * sizeof(gpt_entry_t));
     421                label->parts->fill -= 1;
     422        }
     423       
     424        /* FIXME: This probably shouldn't be here, but instead
     425         * in reduce_part_array() or similar */
    480426        if (label->parts->fill < (label->parts->arr_size / 2) - GPT_IGNORE_FILL_NUM) {
    481                 for (p = gpt_get_partition_at(label, label->parts->arr_size / 2);
    482                      p < label->parts->part_array + label->parts->arr_size; ++p) {
    483                                 if (gpt_get_part_type(p) != GPT_PTE_UNUSED)
    484                                         return EOK;
    485                 }
    486                
    487427                if (reduce_part_array(label->parts) == ENOMEM)
    488428                        return ENOMEM;
     
    508448{
    509449        size_t i;
    510        
    511450        for (i = 0; gpt_ptypes[i].guid != NULL; i++) {
    512                 if (p->part_type[3] == get_byte(gpt_ptypes[i].guid +0) &&
    513                         p->part_type[2] == get_byte(gpt_ptypes[i].guid +2) &&
    514                         p->part_type[1] == get_byte(gpt_ptypes[i].guid +4) &&
    515                         p->part_type[0] == get_byte(gpt_ptypes[i].guid +6) &&
    516                        
    517                         p->part_type[5] == get_byte(gpt_ptypes[i].guid +8) &&
    518                         p->part_type[4] == get_byte(gpt_ptypes[i].guid +10) &&
    519                        
    520                         p->part_type[7] == get_byte(gpt_ptypes[i].guid +12) &&
    521                         p->part_type[6] == get_byte(gpt_ptypes[i].guid +14) &&
    522                        
    523                         p->part_type[8] == get_byte(gpt_ptypes[i].guid +16) &&
    524                         p->part_type[9] == get_byte(gpt_ptypes[i].guid +18) &&
    525                         p->part_type[10] == get_byte(gpt_ptypes[i].guid +20) &&
    526                         p->part_type[11] == get_byte(gpt_ptypes[i].guid +22) &&
    527                         p->part_type[12] == get_byte(gpt_ptypes[i].guid +24) &&
    528                         p->part_type[13] == get_byte(gpt_ptypes[i].guid +26) &&
    529                         p->part_type[14] == get_byte(gpt_ptypes[i].guid +28) &&
    530                         p->part_type[15] == get_byte(gpt_ptypes[i].guid +30))
    531                                 break;
    532         }
    533        
     451                if (bcmp(p->part_type, gpt_ptypes[i].guid, 16) == 0) {
     452                        break;
     453                }
     454        }
    534455        return i;
    535456}
     
    595516
    596517/** Copy partition name */
    597 void gpt_set_part_name(gpt_part_t *p, char *name, size_t length)
     518void gpt_set_part_name(gpt_part_t * p, char * name[], size_t length)
    598519{
    599520        if (length >= 72)
     
    724645}
    725646
    726 static uint8_t get_byte(const char * c)
    727 {
    728         uint8_t val = 0;
    729         char hex[3] = {*c, *(c+1), 0};
    730        
    731         errno = str_uint8_t(hex, NULL, 16, false, &val);
    732         return val;
    733 }
    734 
    735 static int check_overlap(gpt_part_t * p1, gpt_part_t * p2)
    736 {
    737         if (gpt_get_start_lba(p1) < gpt_get_start_lba(p2) && gpt_get_end_lba(p1) <= gpt_get_start_lba(p2)) {
    738                 return 0;
    739         } else if (gpt_get_start_lba(p1) > gpt_get_start_lba(p2) && gpt_get_end_lba(p2) <= gpt_get_start_lba(p1)) {
    740                 return 0;
    741         }
    742 
    743         return 1;
    744 }
    745 
    746 
     647
     648
     649
     650
     651
Note: See TracChangeset for help on using the changeset viewer.