Changes in / [0712ff2:cd3e6a2] in mainline


Ignore:
File:
1 edited

Legend:

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

    r0712ff2 rcd3e6a2  
    3838 * and provides one for each partition.
    3939 *
    40  * Limitations:
    41  *
    4240 * Only works with boot records using LBA. CHS-only records are not
    43  * supported. Maximum number of partitions is fixed.
     41 * supported. Only primary partition records are supported.
    4442 */
    4543
    4644#include <stdio.h>
    47 #include <stdlib.h>
    4845#include <unistd.h>
    4946#include <ipc/ipc.h>
     
    5956#include <bool.h>
    6057#include <byteorder.h>
    61 #include <assert.h>
    6258#include <macros.h>
    6359#include <task.h>
     
    7066
    7167        /** Boot record signature */
    72         BR_SIGNATURE    = 0xAA55,
     68        BR_SIGNATURE    = 0xAA55
    7369};
    7470
    75 enum ptype {
    76         /** Extended partition */
    77         PT_EXTENDED     = 0x05
    78 };
    79 
    8071/** Partition */
    81 typedef struct part {
     72typedef struct {
    8273        /** Primary partition entry is in use */
    8374        bool present;
     
    8879        /** Device representing the partition (outbound device) */
    8980        dev_handle_t dev;
    90         /** Points to next partition structure. */
    91         struct part *next;
    9281} part_t;
    9382
     
    9786        /** CHS of fist block in partition */
    9887        uint8_t first_chs[3];
     88        /** CHS of last block in partition */
     89        uint8_t last_chs[3];
    9990        /** Partition type */
    10091        uint8_t ptype;
    101         /** CHS of last block in partition */
    102         uint8_t last_chs[3];
    10392        /** LBA of first block in partition */
    10493        uint32_t first_lba;
     
    130119static dev_handle_t indev_handle;
    131120
    132 /** List of partitions. This structure is an empty head. */
    133 static part_t plist_head;
     121static part_t primary[N_PRIMARY];
    134122
    135123static int mbr_init(const char *dev_name);
    136124static int mbr_part_read(void);
    137 static part_t *mbr_part_new(void);
    138 static void mbr_pte_to_part(uint32_t base, const pt_entry_t *pte, part_t *part);
    139125static void mbr_connection(ipc_callid_t iid, ipc_call_t *icall);
    140126static int mbr_bd_read(part_t *p, uint64_t ba, size_t cnt, void *buf);
     
    142128static int mbr_bsa_translate(part_t *p, uint64_t ba, size_t cnt, uint64_t *gba);
    143129
     130
    144131int main(int argc, char **argv)
    145132{
    146133        printf(NAME ": PC MBR partition driver\n");
     134        printf(NAME ": Size of br_block_t = %d\n", sizeof(br_block_t));
    147135
    148136        if (argc != 2) {
     
    169157        dev_handle_t dev;
    170158        uint64_t size_mb;
    171         part_t *part;
    172159
    173160        rc = devmap_device_get_handle(dev_name, &indev_handle, 0);
     
    208195        }
    209196
    210         /*
    211          * Create partition devices.
    212          */
    213         i = 0;
    214         part = plist_head.next;
    215 
    216         while (part != NULL) {
     197        /* Create partition devices. */
     198        for (i = 0; i < N_PRIMARY; ++i) {
    217199                /* Skip absent partitions. */
    218                 if (!part->present) {
    219                         part = part->next;
    220                         ++i;
     200                if (!primary[i].present)
    221201                        continue;
    222                 }
    223202
    224203                asprintf(&name, "%sp%d", dev_name, i);
    225                 if (name == NULL)
    226                         return ENOMEM;
    227 
    228204                rc = devmap_device_register(name, &dev);
    229205                if (rc != EOK) {
     
    233209                }
    234210
    235                 size_mb = (part->length * block_size + 1024 * 1024 - 1)
     211                size_mb = (primary[i].length * block_size + 1024 * 1024 - 1)
    236212                    / (1024 * 1024);
    237213                printf(NAME ": Registered device %s: %llu blocks %llu MB.\n",
    238                     name, part->length, size_mb);
    239 
    240                 part->dev = dev;
    241                 free(name);
    242 
    243                 part = part->next;
    244                 ++i;
     214                    name, primary[i].length, size_mb);
     215
     216                primary[i].dev = dev;
    245217        }
    246218
     
    252224{
    253225        int i, rc;
    254         br_block_t *brb;
     226        br_block_t *mbr;
    255227        uint16_t sgn;
    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);
     228        uint32_t sa, len;
     229
     230        rc = block_bb_read(indev_handle, 0);
    272231        if (rc != EOK) {
    273232                printf(NAME ": Failed reading MBR block.\n");
     
    275234        }
    276235
    277         sgn = uint16_t_le2host(brb->signature);
     236        mbr = block_bb_get(indev_handle);
     237        sgn = uint16_t_le2host(mbr->signature);
     238
    278239        if (sgn != BR_SIGNATURE) {
    279240                printf(NAME ": Invalid boot record signature 0x%04X.\n", sgn);
     
    281242        }
    282243
    283         ext_part = NULL;
    284         plist_head.next = NULL;
    285         prev = &plist_head;
    286 
    287244        for (i = 0; i < N_PRIMARY; ++i) {
    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. */
    351 static part_t *mbr_part_new(void)
    352 {
    353         return malloc(sizeof(part_t));
    354 }
    355 
    356 /** Parse partition table entry. */
    357 static 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;
     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        }
    370254}
    371255
     
    382266        uint64_t ba;
    383267        size_t cnt;
     268        int pidx, i;
    384269        part_t *part;
    385270
     
    387272        dh = IPC_GET_ARG1(*icall);
    388273
    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) {
     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*/) {
    399281                ipc_answer_0(iid, EINVAL);
    400282                return;
    401283        }
    402284
    403         assert(part->present == true);
     285        part = &primary[pidx];
    404286
    405287        /* Answer the IPC_M_CONNECT_ME_TO call. */
Note: See TracChangeset for help on using the changeset viewer.