Changeset d617050 in mainline


Ignore:
Timestamp:
2013-04-20T01:13:44Z (11 years ago)
Author:
Dominik Taborsky (AT DOT) <brembyseznamcz>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
8f6c7785
Parents:
e91d17a
Message:

mbr && gpt fix

Location:
uspace/lib
Files:
4 edited

Legend:

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

    re91d17a rd617050  
    5656static int reduce_part_array(gpt_partitions_t * p);
    5757static long long nearest_larger_int(double a);
     58static int gpt_memcmp(const void * a, const void * b, size_t len);
    5859
    5960/** Read GPT from specific device
    6061 * @param       dev_handle      device to read GPT from
    61  * 
     62 *
    6263 * @return                              GPT record on success, NULL on error
    6364 */
     
    6667        int rc;
    6768        size_t b_size;
    68        
     69
    6970        rc = block_get_bsize(dev_handle, &b_size);
    7071        if (rc != EOK) {
     
    7273                return NULL;
    7374        }
    74        
     75
    7576        gpt_t * gpt = malloc(sizeof(gpt_t));
    7677        if (gpt == NULL) {
     
    7879                return NULL;
    7980        }
    80        
     81
    8182        gpt->raw_data = malloc(b_size);// We might need only sizeof(gpt_header_t),
    82         if (gpt == NULL) {                              // but we should follow specs and have 
     83        if (gpt == NULL) {                              // but we should follow specs and have
    8384                free(gpt);                                      // zeroes through all the rest of the block
    8485                errno = ENOMEM;
    8586                return NULL;
    8687        }
    87        
    88        
     88
     89
    8990        rc = load_and_check_header(dev_handle, GPT_HDR_BA, b_size, gpt->raw_data);
    9091        if (rc == EBADCHECKSUM || rc == EINVAL) {
     
    9596                        goto fail;
    9697                }
    97                
     98
    9899                rc = load_and_check_header(dev_handle, n_blocks - 1, b_size, gpt->raw_data);
    99100                if (rc == EBADCHECKSUM || rc == EINVAL) {
     
    102103                }
    103104        }
    104        
     105
    105106        gpt->device = dev_handle;
    106        
     107
    107108        return gpt;
    108109
     
    115116 * @param header                GPT header to be written
    116117 * @param dev_handle    device handle to write the data to
    117  * 
     118 *
    118119 * @return                              0 on success, libblock error code otherwise
    119  * 
     120 *
    120121 * Note: Firstly write partitions (if changed), then gpt header.
    121122 */
     
    124125        int rc;
    125126        size_t b_size;
    126        
     127
    127128        gpt->raw_data->header_crc32 = 0;
    128129        gpt->raw_data->header_crc32 = compute_crc32((uint8_t *) gpt->raw_data,
    129130                                        uint32_t_le2host(gpt->raw_data->header_size));
    130        
     131
    131132        rc = block_get_bsize(dev_handle, &b_size);
    132133        if (rc != EOK)
    133134                return rc;
    134        
     135
    135136        rc = block_init(EXCHANGE_ATOMIC, dev_handle, b_size);
    136137        if (rc != EOK)
    137138                return rc;
    138        
     139
    139140        /* Write to main GPT header location */
    140141        rc = block_write_direct(dev_handle, GPT_HDR_BA, GPT_HDR_BS, gpt->raw_data);
     
    142143                block_fini(dev_handle);
    143144                return rc;
    144        
     145
    145146        aoff64_t n_blocks;
    146147        rc = block_get_nblocks(dev_handle, &n_blocks);
    147148        if (rc != EOK)
    148149                return rc;
    149        
     150
    150151        /* Write to backup GPT header location */
    151152        //FIXME: those idiots thought it would be cool to have these fields in reverse order...
     
    154155        if (rc != EOK)
    155156                return rc;
    156                
     157
    157158        return 0;
    158159}
     
    160161/** Parse partitions from GPT
    161162 * @param gpt   GPT to be parsed
    162  * 
     163 *
    163164 * @return              partition linked list pointer or NULL on error
    164165 *                              error code is stored in errno
     
    172173        uint32_t ent_size = uint32_t_le2host(gpt->raw_data->entry_size);
    173174        uint64_t ent_lba = uint64_t_le2host(gpt->raw_data->entry_lba);
    174        
     175
    175176        res = alloc_part_array(fill);
    176177        if (res == NULL) {
     
    178179                return NULL;
    179180        }
    180        
     181
    181182        /* We can limit comm_size like this:
    182183         *  - we don't need more bytes
     
    188189                return NULL;
    189190        }
    190        
     191
    191192        size_t block_size;
    192193        rc = block_get_bsize(gpt->device, &block_size);
     
    196197                return NULL;
    197198        }
    198        
     199
    199200        //size_t bufpos = 0;
    200201        //size_t buflen = 0;
    201202        aoff64_t pos = ent_lba * block_size;
    202        
     203
    203204        /* Now we read just sizeof(gpt_entry_t) bytes for each entry from the device.
    204205         * Hopefully, this does not bypass cache (no mention in libblock.c),
     
    212213                //rc = block_seqread(gpt->device, &bufpos, &buflen, &pos, res->part_array[i], sizeof(gpt_entry_t));
    213214                pos += ent_size;
    214                
     215
    215216                if (rc != EOK) {
    216217                        gpt_free_partitions(res);
     
    219220                }
    220221        }
    221        
     222
    222223        /* FIXME: so far my boasting about variable partition entry size
    223224         * will not work. The CRC32 checksums will be different.
     
    226227         */
    227228        uint32_t crc = compute_crc32((uint8_t *) res->part_array, res->fill * sizeof(gpt_entry_t));
    228        
     229
    229230        if(uint32_t_le2host(gpt->raw_data->pe_array_crc32) != crc)
    230231        {
     
    233234                return NULL;
    234235        }
    235        
     236
    236237        return res;
    237238}
     
    241242 * @param header                GPT header belonging to the 'parts' partitions
    242243 * @param dev_handle    device to write the data to
    243  * 
     244 *
    244245 * @return                              returns EOK on succes, specific error code otherwise
    245246 */
     
    248249        int rc;
    249250        size_t b_size;
    250        
     251
    251252        gpt->raw_data->pe_array_crc32 = compute_crc32((uint8_t *) parts->part_array, parts->fill * gpt->raw_data->entry_size);
    252        
     253
    253254        rc = block_get_bsize(dev_handle, &b_size);
    254255        if (rc != EOK)
    255256                return rc;
    256        
     257
    257258        rc = block_init(EXCHANGE_ATOMIC, dev_handle, b_size);
    258259        if (rc != EOK)
    259260                return rc;
    260        
     261
    261262        /* Write to main GPT partition array location */
    262         rc = block_write_direct(dev_handle, uint64_t_le2host(gpt->raw_data->entry_lba), 
    263                         nearest_larger_int((uint64_t_le2host(gpt->raw_data->entry_size) * parts->fill) / b_size), 
     263        rc = block_write_direct(dev_handle, uint64_t_le2host(gpt->raw_data->entry_lba),
     264                        nearest_larger_int((uint64_t_le2host(gpt->raw_data->entry_size) * parts->fill) / b_size),
    264265                        parts->part_array);
    265266        if (rc != EOK)
    266267                block_fini(dev_handle);
    267268                return rc;
    268        
     269
    269270        aoff64_t n_blocks;
    270271        rc = block_get_nblocks(dev_handle, &n_blocks);
    271272        if (rc != EOK)
    272273                return rc;
    273        
     274
    274275        /* Write to backup GPT partition array location */
    275276        //rc = block_write_direct(dev_handle, n_blocks - 1, GPT_HDR_BS, header->raw_data);
     
    277278        if (rc != EOK)
    278279                return rc;
    279        
    280        
     280
     281
    281282        return gpt_write_gpt_header(gpt, dev_handle);
    282283}
    283284
    284285/** Alloc new partition
    285  * 
     286 *
    286287 * @param parts         partition table to carry new partition
    287  * 
     288 *
    288289 * @return                      returns pointer to the new partition or NULL on ENOMEM
    289  * 
     290 *
    290291 * Note: use either gpt_alloc_partition or gpt_add_partition. The first
    291  * returns a pointer to write your data to, the second copies the data 
     292 * returns a pointer to write your data to, the second copies the data
    292293 * (and does not free the memory).
    293294 */
     
    298299                        return NULL;
    299300        }
    300        
     301
    301302        return parts->part_array + parts->fill++;
    302303}
    303304
    304305/** Copy partition into partition array
    305  * 
     306 *
    306307 * @param parts                 target partition array
    307308 * @param partition             source partition to copy
    308  * 
     309 *
    309310 * @return                              -1 on error, 0 otherwise
    310  * 
     311 *
    311312 * Note: use either gpt_alloc_partition or gpt_add_partition. The first
    312  * returns a pointer to write your data to, the second copies the data 
     313 * returns a pointer to write your data to, the second copies the data
    313314 * (and does not free the memory).
    314315 */
     
    317318        if (parts->fill == parts->arr_size) {
    318319                if (extend_part_array(parts) == -1)
    319                         return -1;
     320                        return ENOMEM;
    320321        }
    321322        extend_part_array(parts);
    322         return parts;
     323        return EOK;;
    323324}
    324325
    325326/** Remove partition from array
    326  * 
     327 *
    327328 * @param idx           index of the partition to remove
    328  * 
     329 *
    329330 * @return                      -1 on error, 0 otherwise
    330  * 
     331 *
    331332 * Note: even if it fails, the partition still gets removed. Only
    332333 * reducing the array failed.
     
    335336{
    336337        if (idx != parts->fill - 1) {
    337                 memcpy(parts->part_array + idx, parts->part_array + fill - 1, sizeof(gpt_entry_t));
     338                memcpy(parts->part_array + idx, parts->part_array + parts->fill - 1, sizeof(gpt_entry_t));
    338339                parts->fill -= 1;
    339340        }
    340        
     341
    341342        if (parts->fill < (parts->arr_size / 2) - GPT_IGNORE_FILL_NUM) {
    342343                if (reduce_part_array(parts) == -1)
    343344                        return -1;
    344345        }
    345        
     346
    346347        return 0;
    347348}
     
    355356
    356357/** Free partition list
    357  * 
     358 *
    358359 * @param parts         partition list to be freed
    359360 */
     
    371372        size_t i;
    372373        for (i = 0; gpt_ptypes[i].guid != NULL; i++) {
    373                 if (memcmp(p->raw_data.part_type, gpt_ptypes[i].guid, 16) == 0) {
     374                if (gpt_memcmp(p->part_type, gpt_ptypes[i].guid, 16) == 0) {
    374375                        break;
    375376                }
     
    381382 * @param p                     partition to be set
    382383 * @param type          partition type to set
    383  *                                      - see gpt_ptypes to choose from
    384  *
    385  */
    386 void gpt_set_part_type(gpt_part_t * p, int type)
     384 *                                      - see our fine selection at gpt_ptypes to choose from
     385 */
     386void gpt_set_part_type(gpt_part_t * p, size_t type)
    387387{
    388388        /* Beware: first 3 blocks are byteswapped! */
    389         p->raw_data.part_type[3] = gpt_ptypes[type].guid[0];
    390         p->raw_data.part_type[2] = gpt_ptypes[type].guid[1];
    391         p->raw_data.part_type[1] = gpt_ptypes[type].guid[2];
    392         p->raw_data.part_type[0] = gpt_ptypes[type].guid[3];
    393        
    394         p->raw_data.part_type[5] = gpt_ptypes[type].guid[4];
    395         p->raw_data.part_type[4] = gpt_ptypes[type].guid[5];
    396        
    397         p->raw_data.part_type[7] = gpt_ptypes[type].guid[6];
    398         p->raw_data.part_type[6] = gpt_ptypes[type].guid[7];
    399        
    400         p->raw_data.part_type[8] = gpt_ptypes[type].guid[8];
    401         p->raw_data.part_type[9] = gpt_ptypes[type].guid[9];
    402         p->raw_data.part_type[10] = gpt_ptypes[type].guid[10];
    403         p->raw_data.part_type[11] = gpt_ptypes[type].guid[11];
    404         p->raw_data.part_type[12] = gpt_ptypes[type].guid[12];
    405         p->raw_data.part_type[13] = gpt_ptypes[type].guid[13];
    406         p->raw_data.part_type[14] = gpt_ptypes[type].guid[14];
    407         p->raw_data.part_type[15] = gpt_ptypes[type].guid[15];
    408 }
    409 
    410 char * gpt_get_part_name(gpt_entry_t * p)
    411 {
    412         return p->raw_data.part_name;
     389        p->part_type[3] = gpt_ptypes[type].guid[0];
     390        p->part_type[2] = gpt_ptypes[type].guid[1];
     391        p->part_type[1] = gpt_ptypes[type].guid[2];
     392        p->part_type[0] = gpt_ptypes[type].guid[3];
     393
     394        p->part_type[5] = gpt_ptypes[type].guid[4];
     395        p->part_type[4] = gpt_ptypes[type].guid[5];
     396
     397        p->part_type[7] = gpt_ptypes[type].guid[6];
     398        p->part_type[6] = gpt_ptypes[type].guid[7];
     399
     400        p->part_type[8] = gpt_ptypes[type].guid[8];
     401        p->part_type[9] = gpt_ptypes[type].guid[9];
     402        p->part_type[10] = gpt_ptypes[type].guid[10];
     403        p->part_type[11] = gpt_ptypes[type].guid[11];
     404        p->part_type[12] = gpt_ptypes[type].guid[12];
     405        p->part_type[13] = gpt_ptypes[type].guid[13];
     406        p->part_type[14] = gpt_ptypes[type].guid[14];
     407        p->part_type[15] = gpt_ptypes[type].guid[15];
     408}
     409
     410/** Get partition starting LBA */
     411uint64_t gpt_get_start_lba(gpt_part_t * p)
     412{
     413        return uint64_t_le2host(p->start_lba);
     414}
     415
     416/** Set partition starting LBA */
     417void gpt_set_start_lba(gpt_part_t * p, uint64_t start)
     418{
     419        p->start_lba = host2uint64_t_le(start);
     420}
     421
     422/** Get partition ending LBA */
     423uint64_t gpt_get_end_lba(gpt_part_t * p)
     424{
     425        return uint64_t_le2host(p->end_lba);
     426}
     427
     428/** Set partition ending LBA */
     429void gpt_set_end_lba(gpt_part_t * p, uint64_t end)
     430{
     431        p->end_lba = host2uint64_t_le(end);
     432}
     433
     434
     435unsigned char * gpt_get_part_name(gpt_part_t * p)
     436{
     437        return p->part_name;
    413438}
    414439
    415440/** Copy partition name */
    416 void gpt_set_part_name(gpt_entry_t * p, char * name[], size_t length)
     441void gpt_set_part_name(gpt_part_t * p, char * name[], size_t length)
    417442{
    418443        if (length >= 72)
    419444                length = 71;
    420        
     445
    421446        memcpy(p->part_name, name, length);
    422447        p->part_name[length] = '\0';
     
    424449
    425450/** Get partition attribute */
    426 extern bool gpt_get_flag(gpt_part_t * p, GPT_ATTR flag)
    427 {
    428         return (p->raw_data.attributes & (((uint64_t) 1) << flag)) ? 1 : 0;
     451bool gpt_get_flag(gpt_part_t * p, GPT_ATTR flag)
     452{
     453        return (p->attributes & (((uint64_t) 1) << flag)) ? 1 : 0;
    429454}
    430455
    431456/** Set partition attribute */
    432 extern void gpt_set_flag(gpt_part_t * p, GPT_ATTR flag, bool value)
    433 {
    434         uint64_t attr = p->raw_data.attributes;
     457void gpt_set_flag(gpt_part_t * p, GPT_ATTR flag, bool value)
     458{
     459        uint64_t attr = p->attributes;
    435460
    436461        if (value)
     
    439464                attr = attr ^ (attr & (((uint64_t) 1) << flag));
    440465
    441         p->raw_data.attributes = attr;
     466        p->attributes = attr;
    442467}
    443468
     
    447472{
    448473        int rc;
    449        
     474
    450475        rc = block_init(EXCHANGE_ATOMIC, dev_handle, b_size);
    451476        if (rc != EOK)
    452477                return rc;
    453        
     478
    454479        rc = block_read_direct(dev_handle, addr, GPT_HDR_BS, header);
    455480        block_fini(dev_handle);
    456481        if (rc != EOK)
    457482                return rc;
    458        
    459        
     483
     484
    460485        unsigned int i;
    461486        /* Check the EFI signature */
     
    464489                        return EINVAL;
    465490        }
    466        
     491
    467492        /* Check the CRC32 of the header */
    468493        uint32_t crc = header->header_crc32;
     
    472497        else
    473498                header->header_crc32 = crc;
    474        
     499
    475500        /* Check for zeroes in the rest of the block */
    476501        for (i = sizeof(gpt_header_t); i < b_size; ++i) {
     
    478503                        return EINVAL;
    479504        }
    480                
     505
    481506        return EOK;
    482507}
     
    489514                return NULL;
    490515        }
    491        
     516
    492517        uint32_t size = num > GPT_BASE_PART_NUM ? num : GPT_BASE_PART_NUM;
    493518        res->part_array = malloc(size * sizeof(gpt_entry_t));
     
    497522                return NULL;
    498523        }
    499        
     524
    500525        res->fill = num;
    501526        res->arr_size = size;
    502        
     527
    503528        return res;
    504529}
     
    512537                return -1;
    513538        }
    514        
     539
    515540        memcpy(tmp, p->part_array, p->fill);
    516541        free(p->part_array);
    517542        p->part_array = tmp;
    518543        p->arr_size = nsize;
    519        
     544
    520545        return 0;
    521546}
     
    530555                        return -1;
    531556                }
    532                
     557
    533558                memcpy(tmp, p->part_array, p->fill < nsize ? p->fill  : nsize);
    534559                free(p->part_array);
     
    536561                p->arr_size = nsize;
    537562        }
    538        
     563
    539564        return 0;
    540565}
     
    546571                return (long long) a;
    547572        }
    548        
     573
    549574        return ((long long) a) + 1;
    550575}
    551576
    552 
    553 
    554 
     577static int gpt_memcmp(const void * a, const void * b, size_t len)
     578{
     579        size_t i;
     580        int diff;
     581        const unsigned char * x = a;
     582        const unsigned char * y = b;
     583
     584        for (i = 0; i < len; i++) {
     585                diff = (int)*(x++) - (int)*(y++);
     586                if (diff != 0) {
     587                        return diff;
     588                }
     589        }
     590        return 0;
     591}
     592
     593
     594
     595
  • uspace/lib/gpt/libgpt.h

    re91d17a rd617050  
    102102} __attribute__((packed)) gpt_entry_t;
    103103
    104 typedef struct g_part {
    105         /** Partition entry is in use */
    106         bool present;
    107         /** Address of first block */
    108         aoff64_t start_addr;
    109         /** Number of blocks */
    110         aoff64_t length;
    111         /** Raw data access */
    112         gpt_entry_t raw_data;   //TODO: a pointer or just a member?
    113 }gpt_part_t;
     104
     105//typedef struct g_part {
     106        ///** Partition entry is in use **/
     107        //bool present;
     108        ///** Address of first block */
     109        //aoff64_t start_addr;
     110        ///** Number of blocks */
     111        //aoff64_t length;
     112        ///** Raw data access */
     113        //gpt_entry_t raw_data; //TODO: a pointer or just a member?
     114//}gpt_part_t;
     115typedef gpt_entry_t gpt_part_t;
     116
    114117
    115118typedef struct gpt_parts {
     
    140143extern int gpt_write_gpt_header(gpt_t * header, service_id_t dev_handle);
    141144
    142 extern gpt_partitions_t * gpt_read_partitions(gpt_t * gpt);
    143 extern int                                gpt_write_partitions(gpt_partitions_t * parts, gpt_t * header, service_id_t dev_handle);
    144 extern gpt_part_t *               gpt_alloc_partition(gpt_partitions_t * parts);
    145 extern int                                gpt_add_partition(gpt_partitions_t * parts, gpt_part_t * partition);
    146 extern int                                gpt_remove_partition(gpt_partitions_t * parts, size_t idx);
    147 extern size_t                     gpt_get_part_type(gpt_part_t * p);
    148 extern void                       gpt_set_part_type(gpt_part_t * p, size_t type);
    149 extern char *                     gpt_get_part_name(gpt_entry_t * p);
    150 extern void                       gpt_set_part_name(gpt_entry_t * p, char * name[], size_t length);
    151 extern bool                               gpt_get_flag(gpt_part_t * p, GPT_ATTR flag);
    152 extern void                               gpt_set_flag(gpt_part_t * p, GPT_ATTR flag, bool value);
     145extern gpt_partitions_t *       gpt_read_partitions     (gpt_t * gpt);
     146extern int                                      gpt_write_partitions    (gpt_partitions_t * parts, gpt_t * header, service_id_t dev_handle);
     147extern gpt_part_t *                     gpt_alloc_partition             (gpt_partitions_t * parts);
     148extern int                                      gpt_add_partition       (gpt_partitions_t * parts, gpt_part_t * partition);
     149extern int                                      gpt_remove_partition(gpt_partitions_t * parts, size_t idx);
     150
     151extern size_t                           gpt_get_part_type       (gpt_part_t * p);
     152extern void                             gpt_set_part_type       (gpt_part_t * p, size_t type);
     153extern void                                     gpt_set_start_lba       (gpt_part_t * p, uint64_t start);
     154extern uint64_t                         gpt_get_start_lba       (gpt_part_t * p);
     155extern void                                     gpt_set_end_lba         (gpt_part_t * p, uint64_t start);
     156extern uint64_t                         gpt_get_end_lba         (gpt_part_t * p);
     157extern unsigned char *          gpt_get_part_name       (gpt_part_t * p);
     158extern void                             gpt_set_part_name       (gpt_part_t * p, char * name[], size_t length);
     159extern bool                                     gpt_get_flag            (gpt_part_t * p, GPT_ATTR flag);
     160extern void                                     gpt_set_flag            (gpt_part_t * p, GPT_ATTR flag, bool value);
     161
     162
    153163
    154164#define gpt_foreach(parts, i, iterator) \
    155                 for(size_t i = 0, gpt_part_t * iterator = parts->part_array;
     165                for(size_t i = 0, gpt_part_t * iterator = parts->part_array; \
    156166                    i < parts->fill; i++, iterator++)
    157167
  • uspace/lib/mbr/libmbr.c

    re91d17a rd617050  
    4848static int decode_logical(mbr_t * mbr, mbr_partitions_t * p, mbr_part_t * ext);
    4949static void encode_part(mbr_part_t * src, pt_entry_t * trgt, uint32_t base);
     50static int check_overlap(mbr_part_t * p1, mbr_part_t * p2);
     51static int check_encaps(mbr_part_t * inner, mbr_part_t * outer);
     52static int check_preceeds(mbr_part_t * preceeder, mbr_part_t * precedee);
    5053
    5154/** Read MBR from specific device
     
    142145                if (mbr->raw_data.pte[i].ptype == PT_UNUSED)
    143146                        continue;
    144                
     147
    145148                p = malloc(sizeof(mbr_part_t));
    146149                if (p == NULL) {
     
    179182int mbr_write_partitions(mbr_partitions_t * parts, mbr_t * mbr, service_id_t dev_handle)
    180183{
    181         bool logical = false;
     184        //bool logical = false;
    182185        int i = 0;
    183186        int rc;
     
    185188        mbr_part_t * ext = (parts->l_extended == NULL) ? NULL
    186189                                        : list_get_instance(parts->l_extended, mbr_part_t, link);
    187        
    188         br_block_t * last_ebr = NULL;
    189         link_t * it;
    190        
     190
     191        //br_block_t * last_ebr = NULL;
     192        //link_t * it;
     193
    191194        DEBUG_PRINT_3(LIBMBR_NAME "Writing partitions: n_primary: %u, n_logical:%u, l_extended:%p", parts->n_primary, parts->n_logical, parts->l_extended);
    192        
     195
    193196        rc = block_init(EXCHANGE_ATOMIC, dev_handle, 512);
    194197        if (rc != EOK) {
     
    196199                return rc;
    197200        }
     201        /*
     202        // Encoding primary partitions
     203        for (i = 0; i < parts->n_primary; i++) {
     204                encode_part(p, &(mbr->raw_data.pte[i]), 0);
     205        }
     206
     207        // Writing MBR
     208        rc = block_write_direct(dev_handle, 0, 1, &(mbr->raw_data));
     209        if (rc != EOK) {
     210                DEBUG_PRINT_2(LIBMBR_NAME ": Error (%d): %s.\n", rc, str_error(rc));
     211                goto end;
     212        }
     213
     214        uint32_t base = ext->start_addr;
     215        uint32_t addr = base;
     216
     217        // Encoding and writing logical partitions
     218        mbr_part_foreach(parts, p) {
     219                if (p->ebr == NULL) {
     220                        p->ebr = alloc_br();
     221                        if (p->ebr == NULL)
     222                        {
     223                                rc = ENOMEM;
     224                                goto end;
     225                        }
     226                }
     227
     228
     229        }*/
     230
     231        link_t * l = parts->list.head.next;
     232
     233        // Encoding primary partitions
     234        for (i = 0; i < parts->n_primary; i++) {
     235                p = list_get_instance(l, mbr_part_t, link);
     236                encode_part(p, &(mbr->raw_data.pte[i]), 0);
     237                l = l->next;
     238        }
     239
     240        // Writing MBR
     241        rc = block_write_direct(dev_handle, 0, 1, &(mbr->raw_data));
     242        if (rc != EOK) {
     243                DEBUG_PRINT_2(LIBMBR_NAME ": Error (%d): %s.\n", rc, str_error(rc));
     244                goto end;
     245        }
    198246
    199247        if (ext == NULL)
    200248                goto no_extended;
    201249
     250
    202251        uint32_t base = ext->start_addr;
    203252        uint32_t addr = base;
     253
     254        // Encoding and writing first logical partition
     255        if (l != &(parts->list.head)) {
     256                p = list_get_instance(l, mbr_part_t, link);
     257                if (p->ebr == NULL) {
     258                        p->ebr = alloc_br();
     259                        if (p->ebr == NULL) {
     260                                rc = ENOMEM;
     261                                goto end;
     262                        }
     263                }
     264
     265                encode_part(p, &(p->ebr->pte[0]), base);
     266
     267                if (l->next == &(parts->list.head))
     268                        encode_part(NULL, &(p->ebr->pte[1]), base);
     269                else
     270                        encode_part(list_get_instance(l->next, mbr_part_t, link), &(p->ebr->pte[1]), base);
     271
     272
     273                rc = block_write_direct(dev_handle, base, 1, p->ebr);
     274                if (rc != EOK) {
     275                        DEBUG_PRINT_2(LIBMBR_NAME ": Error (%d): %s.\n", rc, str_error(rc));
     276                        goto end;
     277                }
     278
     279                l = l->next;
     280        }
     281
     282
     283
     284        // Encoding and writing logical partitions
     285        while (l != &(parts->list.head)) {
     286                p = list_get_instance(l, mbr_part_t, link);
     287                if (p->ebr == NULL) {
     288                        p->ebr = alloc_br();
     289                        if (p->ebr == NULL) {
     290                                rc = ENOMEM;
     291                                goto end;
     292                        }
     293                }
     294
     295                addr = p->start_addr - base;
     296                encode_part(p, &(p->ebr->pte[0]), addr);
     297
     298                if (l->next == &(parts->list.head))
     299                        encode_part(NULL, &(p->ebr->pte[1]), base);
     300                else
     301                        encode_part(list_get_instance(l->next, mbr_part_t, link), &(p->ebr->pte[1]), base);
     302
     303
     304                rc = block_write_direct(dev_handle, addr, 1, p->ebr);
     305                if (rc != EOK) {
     306                        DEBUG_PRINT_2(LIBMBR_NAME ": Error (%d): %s.\n", rc, str_error(rc));
     307                        goto end;
     308                }
     309
     310                l = l->next;
     311        }
     312
     313no_extended:
     314
     315        /*if (ext == NULL)
     316                goto no_extended;
     317
     318        uint32_t base = ext->start_addr;
     319        uint32_t addr;// = base;
    204320        uint32_t prev_addr;
    205321        mbr_part_t * prev_part = NULL;
     
    209325                if (mbr_get_flag(p, ST_LOGIC)) {
    210326                        // writing logical partition
    211                        
    212                         if (p->start_addr < base || p->start_addr + p->length > base + ext->length) {
    213                                 // out of bounds
    214                                 return EINVAL;
    215                         }
    216                        
    217                        
     327                        logical = true;
     328
    218329                        if (p->ebr == NULL) {
    219330                                p->ebr = alloc_br();
     
    225336                        }
    226337
    227                        
    228                        
    229                        
    230338                        if (prev_part != NULL) {
    231339                                // addr is the address of EBR
     
    243351                                addr = base;
    244352                                // base-1 means start_lba+1
    245                                 encode_part(p, &(p->ebr->pte[0]), base - 1);
     353                                // Fixed: mbr_add_partition now performs checks!nevim
     354                                encode_part(p, &(p->ebr->pte[0]), base);
    246355                        }
    247                        
     356
    248357                        //addr = p->start_addr;
    249358                        prev_addr = addr;
     
    260369                        ++i;
    261370                }
    262         }
     371        } //*/
    263372
    264373        /* If there was an extended but no logical, we should overwrite
     
    266375         * might be some garbage from the past.
    267376         */
    268        
     377        /*
    269378        last_ebr = prev_part->ebr;
    270        
     379
    271380        if (!logical)
    272381        {
     
    276385                        goto end;
    277386                }
    278                
     387
    279388                last_ebr->pte[0].ptype = PT_UNUSED;
    280389        }
    281        
    282        
     390
     391
    283392        encode_part(NULL, &(last_ebr->pte[1]), 0);
    284393        rc = block_write_direct(dev_handle, addr, 1, last_ebr);
    285        
     394
    286395        if (!logical)
    287396        {
    288397                free(last_ebr);
    289398        }
    290        
     399        */
     400        /*
    291401        if (rc != EOK) {
    292402                DEBUG_PRINT_2(LIBMBR_NAME ": Error (%d): %s.\n", rc, str_error(rc));
     
    297407
    298408no_extended:
    299 
     409        */
    300410        /*list_foreach(parts->list, it) {
    301411                p = list_get_instance(it, mbr_part_t, link);
     
    313423                }
    314424        }*/
    315        
     425        /*
    316426        it = parts->list.head.next;
    317427        for (i = 0; i < N_PRIMARY; i++) {
     
    329439
    330440                        }
    331                        
     441
    332442                        it = it->next;
    333443                } else {
     
    335445                }
    336446        }
    337        
     447
    338448
    339449skip:
     
    343453                goto end;
    344454        }
     455        */
    345456
    346457        /*
     
    405516
    406517        rc = EOK;
    407        
     518
    408519end:
    409520        block_fini(dev_handle);
     
    437548
    438549        list_initialize(&(parts->list));
    439        
     550
    440551        parts->n_primary = 0;
    441552        parts->n_logical = 0;
     
    445556}
    446557
    447 /** Add partition */
     558/** Add partition
     559 *      Performs checks, sorts the list.
     560 */
    448561int mbr_add_partition(mbr_partitions_t * parts, mbr_part_t * p)
    449562{
    450         list_append(&(p->link), &(parts->list));
    451563        if (mbr_get_flag(p, ST_LOGIC)) {
     564                // adding logical part
     565                if (parts->l_extended == NULL) {
     566                        return ERR_NO_EXTENDED;
     567                }
     568                if (!check_encaps(p, list_get_instance(parts->l_extended, mbr_part_t, link))) {
     569                        return ERR_OUT_BOUNDS;
     570                }
     571
     572                mbr_part_t * last = list_get_instance(list_last(&(parts->list)), mbr_part_t, link);
     573                mbr_part_foreach(parts, iter) {
     574                        if (mbr_get_flag(iter, ST_LOGIC)) {
     575                                if (check_overlap(p, iter)) {
     576                                        return ERR_OVERLAP;
     577                                }
     578                                if (check_preceeds(p, iter)) {
     579                                        last = iter;
     580                                        break;
     581                                }
     582                        }
     583                }
     584
     585                //list_prepend(&(p->link), &(parts->list));
     586                list_insert_before(&(p->link), &(last->link));
    452587                parts->n_logical += 1;
    453588        } else {
    454                 parts->n_primary += 1;
    455         }
    456         /* if we're adding new logical partition, we need 1 sector for the EBR
    457          * for that partition (including the next one); we'd better make sure here
    458          * before writing */
    459         if (mbr_get_flag(p, ST_LOGIC) && p->ebr == NULL) {
    460                 p->start_addr += 1;
    461                 p->length -= 1;
    462         }
    463         //FIXME: we can have multiple extended partitions! :-(
    464        
    465         return EOK;
     589                // adding primary
     590                if (parts->n_primary == 4) {
     591                        return ERR_PRIMARY_FULL;
     592                }
     593                if (p->type == PT_EXTENDED && parts->l_extended != NULL) {
     594                        return ERR_EXTENDED_PRESENT;
     595                }
     596
     597                if (list_empty(&(parts->list))) {
     598                        list_append(&(p->link), &(parts->list));
     599                } else {
     600                        mbr_part_foreach(parts, iter) {
     601                                if (mbr_get_flag(iter, ST_LOGIC)) {
     602                                        list_insert_before(&(p->link), &(iter->link));
     603                                        parts->n_primary += 1;
     604                                        break;
     605                                } else if (check_overlap(p, iter)) {
     606                                        return ERR_OVERLAP;
     607                                }
     608                        }
     609                }
     610        }
     611
     612        return ERR_OK;
    466613}
    467614
     
    469616int mbr_remove_partition(mbr_partitions_t * parts, size_t idx)
    470617{
    471         DEBUG_PRINT_1(LIBMBR_NAME "Removing partition: %d\n", idx);
     618        DEBUG_PRINT_1(LIBMBR_NAME "Removing partition: %zu\n", idx);
    472619        link_t * l = list_nth(&(parts->list), idx);
    473620        if (l == parts->l_extended) {
     
    482629                parts->n_primary -= 1;
    483630        }
    484        
    485        
     631
     632
    486633        mbr_free_partition(p);
    487        
     634
    488635        return EOK;
    489636}
     
    533680                mbr_free_partition(p);
    534681        }
    535        
     682
    536683        free(parts);
    537684}
     
    590737        if (rc != EOK)
    591738                return rc;
    592        
     739
    593740        ebr = alloc_br();
    594741        if (ebr == NULL) {
     
    606753                goto free_ebr_end;
    607754        }
    608        
     755
    609756        if (ebr->pte[0].ptype == PT_UNUSED) {
    610757                rc = EOK;
    611758                goto free_ebr_end;
    612759        }
    613        
     760
    614761        p = mbr_alloc_partition();
    615762        if (p == NULL) {
     
    617764                goto free_ebr_end;
    618765        }
    619        
     766
    620767
    621768        decode_part(&(ebr->pte[0]), p, base);
     
    625772
    626773        addr = uint32_t_le2host(ebr->pte[1].first_lba) + base;
    627        
     774
    628775        while (ebr->pte[1].ptype != PT_UNUSED) {
    629776                ebr = alloc_br();
     
    656803                addr = uint32_t_le2host(ebr->pte[1].first_lba) + base;
    657804        }
    658        
     805
    659806        rc = EOK;
    660        
     807
    661808free_ebr_end:
    662809        free(ebr);
    663        
     810
    664811end:
    665812        block_fini(mbr->device);
     
    690837}
    691838
     839static int check_overlap(mbr_part_t * p1, mbr_part_t * p2)
     840{
     841        if (p1->start_addr < p2->start_addr && p1->start_addr + p1->length <= p2->start_addr) {
     842                return 0;
     843        } else if (p1->start_addr > p2->start_addr && p2->start_addr + p2->length <= p1->start_addr) {
     844                return 0;
     845        }
     846
     847        return 1;
     848}
     849
     850static int check_encaps(mbr_part_t * inner, mbr_part_t * outer)
     851{
     852        if (inner->start_addr <= outer->start_addr || outer->start_addr + outer->length <= inner->start_addr) {
     853                return 0;
     854        } else if (outer->start_addr + outer->length < inner->start_addr + inner->length) {
     855                return 0;
     856        }
     857
     858        return 1;
     859}
     860
     861static int check_preceeds(mbr_part_t * preceeder, mbr_part_t * precedee)
     862{
     863        return preceeder->start_addr < precedee->start_addr;
     864}
     865
     866
     867
  • uspace/lib/mbr/libmbr.h

    re91d17a rd617050  
    5252        printf("%s:%d: " str, __FILE__, __LINE__, arg1, arg2, arg3)
    5353#else
    54 #define DEBUG_PRINT_0(str) 
     54#define DEBUG_PRINT_0(str)
    5555#define DEBUG_PRINT_1(str, arg1)
    5656#define DEBUG_PRINT_2(str, arg1, arg2)
     
    8787        PT_GPT  = 0xEE,
    8888};
     89
     90typedef enum {
     91        /** No error */
     92        ERR_OK = 0,
     93        /** All primary partitions already present */
     94        ERR_PRIMARY_FULL,
     95        /** Extended partition already present */
     96        ERR_EXTENDED_PRESENT,
     97        /** No extended partition present */
     98        ERR_NO_EXTENDED,
     99        /** Partition overlapping */
     100        ERR_OVERLAP,
     101        /** Logical partition out of bounds */
     102        ERR_OUT_BOUNDS,
     103} MBR_ERR_VAL;
     104
    89105
    90106/** Structure of a partition table entry */
     
    146162        /** Number of primary partitions */
    147163        unsigned char n_primary;
    148         /** Link to the extended partition in the list */
     164        /** Index to the extended partition in the array */
    149165        link_t * l_extended;
    150166        /** Number of logical partitions */
    151167        unsigned int n_logical;
    152         /** Partition linked list */
     168        /** Logical partition linked list */
    153169        list_t list;
    154170} mbr_partitions_t;
Note: See TracChangeset for help on using the changeset viewer.