Changeset 0712ff2 in mainline


Ignore:
Timestamp:
2009-09-01T21:33:16Z (15 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
e86a849a
Parents:
cd3e6a2 (diff), e27b89a (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge MBR extended partition support.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/part/mbr_part/mbr_part.c

    rcd3e6a2 r0712ff2  
    3838 * and provides one for each partition.
    3939 *
     40 * Limitations:
     41 *
    4042 * Only works with boot records using LBA. CHS-only records are not
    41  * supported. Only primary partition records are supported.
     43 * supported. Maximum number of partitions is fixed.
    4244 */
    4345
    4446#include <stdio.h>
     47#include <stdlib.h>
    4548#include <unistd.h>
    4649#include <ipc/ipc.h>
     
    5659#include <bool.h>
    5760#include <byteorder.h>
     61#include <assert.h>
    5862#include <macros.h>
    5963#include <task.h>
     
    6670
    6771        /** Boot record signature */
    68         BR_SIGNATURE    = 0xAA55
     72        BR_SIGNATURE    = 0xAA55,
    6973};
    7074
     75enum ptype {
     76        /** Extended partition */
     77        PT_EXTENDED     = 0x05
     78};
     79
    7180/** Partition */
    72 typedef struct {
     81typedef struct part {
    7382        /** Primary partition entry is in use */
    7483        bool present;
     
    7988        /** Device representing the partition (outbound device) */
    8089        dev_handle_t dev;
     90        /** Points to next partition structure. */
     91        struct part *next;
    8192} part_t;
    8293
     
    8697        /** CHS of fist block in partition */
    8798        uint8_t first_chs[3];
     99        /** Partition type */
     100        uint8_t ptype;
    88101        /** CHS of last block in partition */
    89102        uint8_t last_chs[3];
    90         /** Partition type */
    91         uint8_t ptype;
    92103        /** LBA of first block in partition */
    93104        uint32_t first_lba;
     
    119130static dev_handle_t indev_handle;
    120131
    121 static part_t primary[N_PRIMARY];
     132/** List of partitions. This structure is an empty head. */
     133static part_t plist_head;
    122134
    123135static int mbr_init(const char *dev_name);
    124136static int mbr_part_read(void);
     137static part_t *mbr_part_new(void);
     138static void mbr_pte_to_part(uint32_t base, const pt_entry_t *pte, part_t *part);
    125139static void mbr_connection(ipc_callid_t iid, ipc_call_t *icall);
    126140static int mbr_bd_read(part_t *p, uint64_t ba, size_t cnt, void *buf);
     
    128142static int mbr_bsa_translate(part_t *p, uint64_t ba, size_t cnt, uint64_t *gba);
    129143
    130 
    131144int main(int argc, char **argv)
    132145{
    133146        printf(NAME ": PC MBR partition driver\n");
    134         printf(NAME ": Size of br_block_t = %d\n", sizeof(br_block_t));
    135147
    136148        if (argc != 2) {
     
    157169        dev_handle_t dev;
    158170        uint64_t size_mb;
     171        part_t *part;
    159172
    160173        rc = devmap_device_get_handle(dev_name, &indev_handle, 0);
     
    195208        }
    196209
    197         /* Create partition devices. */
    198         for (i = 0; i < N_PRIMARY; ++i) {
     210        /*
     211         * Create partition devices.
     212         */
     213        i = 0;
     214        part = plist_head.next;
     215
     216        while (part != NULL) {
    199217                /* Skip absent partitions. */
    200                 if (!primary[i].present)
     218                if (!part->present) {
     219                        part = part->next;
     220                        ++i;
    201221                        continue;
     222                }
    202223
    203224                asprintf(&name, "%sp%d", dev_name, i);
     225                if (name == NULL)
     226                        return ENOMEM;
     227
    204228                rc = devmap_device_register(name, &dev);
    205229                if (rc != EOK) {
     
    209233                }
    210234
    211                 size_mb = (primary[i].length * block_size + 1024 * 1024 - 1)
     235                size_mb = (part->length * block_size + 1024 * 1024 - 1)
    212236                    / (1024 * 1024);
    213237                printf(NAME ": Registered device %s: %llu blocks %llu MB.\n",
    214                     name, primary[i].length, size_mb);
    215 
    216                 primary[i].dev = dev;
     238                    name, part->length, size_mb);
     239
     240                part->dev = dev;
     241                free(name);
     242
     243                part = part->next;
     244                ++i;
    217245        }
    218246
     
    224252{
    225253        int i, rc;
    226         br_block_t *mbr;
     254        br_block_t *brb;
    227255        uint16_t sgn;
    228         uint32_t sa, len;
    229 
    230         rc = block_bb_read(indev_handle, 0);
     256        uint32_t ba;
     257        part_t *ext_part, cp;
     258        uint32_t base;
     259        part_t *prev, *p;
     260
     261        brb = malloc(sizeof(br_block_t));
     262        if (brb == NULL) {
     263                printf(NAME ": Failed allocating memory.\n");
     264                return ENOMEM; 
     265        }
     266
     267        /*
     268         * Read primary partition entries.
     269         */
     270
     271        rc = block_read_direct(indev_handle, 0, 1, brb);
    231272        if (rc != EOK) {
    232273                printf(NAME ": Failed reading MBR block.\n");
     
    234275        }
    235276
    236         mbr = block_bb_get(indev_handle);
    237         sgn = uint16_t_le2host(mbr->signature);
    238 
     277        sgn = uint16_t_le2host(brb->signature);
    239278        if (sgn != BR_SIGNATURE) {
    240279                printf(NAME ": Invalid boot record signature 0x%04X.\n", sgn);
     
    242281        }
    243282
     283        ext_part = NULL;
     284        plist_head.next = NULL;
     285        prev = &plist_head;
     286
    244287        for (i = 0; i < N_PRIMARY; ++i) {
    245                 sa  = uint32_t_le2host(mbr->pte[i].first_lba);
    246                 len = uint32_t_le2host(mbr->pte[i].length);
    247 
    248                 primary[i].start_addr = sa;
    249                 primary[i].length = len;
    250 
    251                 primary[i].present = (sa != 0 || len != 0) ? true : false;
    252                 primary[i].dev = 0;
    253         }
     288                p = mbr_part_new();
     289                if (p == NULL)
     290                        return ENOMEM;
     291
     292                mbr_pte_to_part(0, &brb->pte[i], p);
     293                prev->next = p;
     294                prev = p;
     295
     296                if (brb->pte[i].ptype == PT_EXTENDED) {
     297                        p->present = false;
     298                        ext_part = p;
     299                }
     300        }
     301
     302        if (ext_part == NULL)
     303                return EOK;
     304
     305        printf("Extended partition found.\n");
     306
     307        /*
     308         * Read extended partition entries.
     309         */
     310
     311        cp.start_addr = ext_part->start_addr;
     312        cp.length = ext_part->length;
     313        base = ext_part->start_addr;
     314
     315        do {
     316                /*
     317                 * Addressing in the EBR chain is relative to the beginning
     318                 * of the extended partition.
     319                 */
     320                ba = cp.start_addr;
     321                rc = block_read_direct(indev_handle, ba, 1, brb);
     322                if (rc != EOK) {
     323                        printf(NAME ": Failed reading EBR block at %u.\n", ba);
     324                        return rc;
     325                }
     326
     327                sgn = uint16_t_le2host(brb->signature);
     328                if (sgn != BR_SIGNATURE) {
     329                        printf(NAME ": Invalid boot record signature 0x%04X "
     330                            " in EBR at %u.\n", sgn, ba);
     331                        return EINVAL;
     332                }
     333
     334                p = mbr_part_new();
     335                if (p == NULL)
     336                        return ENOMEM;
     337
     338                /* First PTE is the logical partition itself. */
     339                mbr_pte_to_part(base, &brb->pte[0], p);
     340                prev->next = p;
     341                prev = p;
     342
     343                /* Second PTE describes next chain element. */
     344                mbr_pte_to_part(base, &brb->pte[1], &cp);
     345        } while (cp.present);
     346
     347        return EOK;
     348}
     349
     350/** Allocate a new @c part_t structure. */
     351static part_t *mbr_part_new(void)
     352{
     353        return malloc(sizeof(part_t));
     354}
     355
     356/** Parse partition table entry. */
     357static void mbr_pte_to_part(uint32_t base, const pt_entry_t *pte, part_t *part)
     358{
     359        uint32_t sa, len;
     360
     361        sa = uint32_t_le2host(pte->first_lba);
     362        len = uint32_t_le2host(pte->length);
     363
     364        part->start_addr = base + sa;
     365        part->length     = len;
     366
     367        part->present = (sa != 0 || len != 0) ? true : false;
     368        part->dev = 0;
     369        part->next = NULL;
    254370}
    255371
     
    266382        uint64_t ba;
    267383        size_t cnt;
    268         int pidx, i;
    269384        part_t *part;
    270385
     
    272387        dh = IPC_GET_ARG1(*icall);
    273388
    274         /* Determine which partition device is the client connecting to. */
    275         pidx = -1;
    276         for (i = 0; i < N_PRIMARY; i++)
    277                 if (primary[i].dev == dh)
    278                         pidx = i;
    279 
    280         if (pidx < 0/* || disk[disk_id].present == false*/) {
     389        /*
     390         * Determine which partition device is the client connecting to.
     391         * A linear search is not terribly fast, but we only do this
     392         * once for each connection.
     393         */
     394        part = plist_head.next;
     395        while (part != NULL && part->dev != dh)
     396                part = part->next;
     397
     398        if (part == NULL) {
    281399                ipc_answer_0(iid, EINVAL);
    282400                return;
    283401        }
    284402
    285         part = &primary[pidx];
     403        assert(part->present == true);
    286404
    287405        /* Answer the IPC_M_CONNECT_ME_TO call. */
Note: See TracChangeset for help on using the changeset viewer.