~jsvoboda/helenos/dnsr

« back to all changes in this revision

Viewing changes to uspace/srv/bd/part/mbr_part/mbr_part.c

  • Committer: Jiri Svoboda
  • Date: 2012-11-11 21:31:03 UTC
  • mfrom: (1527.1.178 mainline)
  • Revision ID: jiri@wiwaxia-20121111213103-314bmkettwvlwj97
MergeĀ mainlineĀ changes.

Show diffs side-by-side

added added

removed removed

Lines of Context:
43
43
 * supported.
44
44
 *
45
45
 * Referemces:
46
 
 *      
 
46
 *
47
47
 * The source of MBR structures for this driver have been the following
48
48
 * Wikipedia articles:
49
49
 *      - http://en.wikipedia.org/wiki/Master_Boot_Record
56
56
#include <stdio.h>
57
57
#include <stdlib.h>
58
58
#include <unistd.h>
59
 
#include <ipc/bd.h>
60
59
#include <async.h>
61
60
#include <as.h>
 
61
#include <bd_srv.h>
62
62
#include <fibril_synch.h>
63
63
#include <loc.h>
64
64
#include <sys/types.h>
65
65
#include <sys/typefmt.h>
66
66
#include <inttypes.h>
67
 
#include <libblock.h>
 
67
#include <block.h>
68
68
#include <errno.h>
69
69
#include <bool.h>
70
70
#include <byteorder.h>
99
99
        aoff64_t length;
100
100
        /** Device representing the partition (outbound device) */
101
101
        service_id_t dsid;
 
102
        /** Block device service sturcture */
 
103
        bd_srvs_t bds;
102
104
        /** Points to next partition structure. */
103
105
        struct part *next;
104
106
} part_t;
139
141
static size_t block_size;
140
142
 
141
143
/** Partitioned device (inbound device) */
142
 
static service_id_t indef_sid;
 
144
static service_id_t indev_sid;
143
145
 
144
146
/** List of partitions. This structure is an empty head. */
145
147
static part_t plist_head;
149
151
static part_t *mbr_part_new(void);
150
152
static void mbr_pte_to_part(uint32_t base, const pt_entry_t *pte, part_t *part);
151
153
static void mbr_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg);
152
 
static int mbr_bd_read(part_t *p, uint64_t ba, size_t cnt, void *buf);
153
 
static int mbr_bd_write(part_t *p, uint64_t ba, size_t cnt, const void *buf);
154
154
static int mbr_bsa_translate(part_t *p, uint64_t ba, size_t cnt, uint64_t *gba);
155
155
 
 
156
static int mbr_bd_open(bd_srvs_t *, bd_srv_t *);
 
157
static int mbr_bd_close(bd_srv_t *);
 
158
static int mbr_bd_read_blocks(bd_srv_t *, aoff64_t, size_t, void *, size_t);
 
159
static int mbr_bd_write_blocks(bd_srv_t *, aoff64_t, size_t, const void *, size_t);
 
160
static int mbr_bd_get_block_size(bd_srv_t *, size_t *);
 
161
static int mbr_bd_get_num_blocks(bd_srv_t *, aoff64_t *);
 
162
 
 
163
static bd_ops_t mbr_bd_ops = {
 
164
        .open = mbr_bd_open,
 
165
        .close = mbr_bd_close,
 
166
        .read_blocks = mbr_bd_read_blocks,
 
167
        .write_blocks = mbr_bd_write_blocks,
 
168
        .get_block_size = mbr_bd_get_block_size,
 
169
        .get_num_blocks = mbr_bd_get_num_blocks
 
170
};
 
171
 
 
172
static part_t *bd_srv_part(bd_srv_t *bd)
 
173
{
 
174
        return (part_t *)bd->srvs->sarg;
 
175
}
 
176
 
156
177
int main(int argc, char **argv)
157
178
{
158
179
        printf(NAME ": PC MBR partition driver\n");
182
203
        uint64_t size_mb;
183
204
        part_t *part;
184
205
 
185
 
        rc = loc_service_get_id(dev_name, &indef_sid, 0);
 
206
        rc = loc_service_get_id(dev_name, &indev_sid, 0);
186
207
        if (rc != EOK) {
187
208
                printf(NAME ": could not resolve device `%s'.\n", dev_name);
188
209
                return rc;
189
210
        }
190
211
 
191
 
        rc = block_init(EXCHANGE_SERIALIZE, indef_sid, 2048);
 
212
        rc = block_init(EXCHANGE_SERIALIZE, indev_sid, 2048);
192
213
        if (rc != EOK)  {
193
214
                printf(NAME ": could not init libblock.\n");
194
215
                return rc;
196
217
 
197
218
        /* Determine and verify block size. */
198
219
 
199
 
        rc = block_get_bsize(indef_sid, &block_size);
 
220
        rc = block_get_bsize(indev_sid, &block_size);
200
221
        if (rc != EOK) {
201
222
                printf(NAME ": error getting block size.\n");
202
223
                return rc;
280
301
         * Read primary partition entries.
281
302
         */
282
303
 
283
 
        rc = block_read_direct(indef_sid, 0, 1, brb);
 
304
        rc = block_read_direct(indev_sid, 0, 1, brb);
284
305
        if (rc != EOK) {
285
306
                printf(NAME ": Failed reading MBR block.\n");
286
307
                return rc;
331
352
                 * of the extended partition.
332
353
                 */
333
354
                ba = cp.start_addr;
334
 
                rc = block_read_direct(indef_sid, ba, 1, brb);
 
355
                rc = block_read_direct(indev_sid, ba, 1, brb);
335
356
                if (rc != EOK) {
336
357
                        printf(NAME ": Failed reading EBR block at %"
337
358
                            PRIu32 ".\n", ba);
380
401
 
381
402
        part->present = (pte->ptype != PT_UNUSED) ? true : false;
382
403
 
 
404
        bd_srvs_init(&part->bds);
 
405
        part->bds.ops = &mbr_bd_ops;
 
406
        part->bds.sarg = part;
 
407
 
383
408
        part->dsid = 0;
384
409
        part->next = NULL;
385
410
}
386
411
 
387
412
static void mbr_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
388
413
{
389
 
        size_t comm_size;
390
 
        void *fs_va = NULL;
391
 
        ipc_callid_t callid;
392
 
        ipc_call_t call;
393
 
        sysarg_t method;
394
414
        service_id_t dh;
395
 
        unsigned int flags;
396
 
        int retval;
397
 
        uint64_t ba;
398
 
        size_t cnt;
399
415
        part_t *part;
400
416
 
401
417
        /* Get the device handle. */
416
432
        }
417
433
 
418
434
        assert(part->present == true);
419
 
 
420
 
        /* Answer the IPC_M_CONNECT_ME_TO call. */
421
 
        async_answer_0(iid, EOK);
422
 
 
423
 
        if (!async_share_out_receive(&callid, &comm_size, &flags)) {
424
 
                async_answer_0(callid, EHANGUP);
425
 
                return;
426
 
        }
427
 
 
428
 
        (void) async_share_out_finalize(callid, &fs_va);
429
 
        if (fs_va == AS_MAP_FAILED) {
430
 
                async_answer_0(callid, EHANGUP);
431
 
                return;
432
 
        }
433
 
 
434
 
        while (1) {
435
 
                callid = async_get_call(&call);
436
 
                method = IPC_GET_IMETHOD(call);
437
 
                
438
 
                if (!method) {
439
 
                        /* The other side has hung up. */
440
 
                        async_answer_0(callid, EOK);
441
 
                        return;
442
 
                }
443
 
                
444
 
                switch (method) {
445
 
                case BD_READ_BLOCKS:
446
 
                        ba = MERGE_LOUP32(IPC_GET_ARG1(call),
447
 
                            IPC_GET_ARG2(call));
448
 
                        cnt = IPC_GET_ARG3(call);
449
 
                        if (cnt * block_size > comm_size) {
450
 
                                retval = ELIMIT;
451
 
                                break;
452
 
                        }
453
 
                        retval = mbr_bd_read(part, ba, cnt, fs_va);
454
 
                        break;
455
 
                case BD_WRITE_BLOCKS:
456
 
                        ba = MERGE_LOUP32(IPC_GET_ARG1(call),
457
 
                            IPC_GET_ARG2(call));
458
 
                        cnt = IPC_GET_ARG3(call);
459
 
                        if (cnt * block_size > comm_size) {
460
 
                                retval = ELIMIT;
461
 
                                break;
462
 
                        }
463
 
                        retval = mbr_bd_write(part, ba, cnt, fs_va);
464
 
                        break;
465
 
                case BD_GET_BLOCK_SIZE:
466
 
                        async_answer_1(callid, EOK, block_size);
467
 
                        continue;
468
 
                case BD_GET_NUM_BLOCKS:
469
 
                        async_answer_2(callid, EOK, LOWER32(part->length),
470
 
                            UPPER32(part->length));
471
 
                        continue;
472
 
                default:
473
 
                        retval = EINVAL;
474
 
                        break;
475
 
                }
476
 
                async_answer_0(callid, retval);
477
 
        }
 
435
        bd_conn(iid, icall, &part->bds);
 
436
}
 
437
 
 
438
/** Open device. */
 
439
static int mbr_bd_open(bd_srvs_t *bds, bd_srv_t *bd)
 
440
{
 
441
        return EOK;
 
442
}
 
443
 
 
444
/** Close device. */
 
445
static int mbr_bd_close(bd_srv_t *bd)
 
446
{
 
447
        return EOK;
478
448
}
479
449
 
480
450
/** Read blocks from partition. */
481
 
static int mbr_bd_read(part_t *p, uint64_t ba, size_t cnt, void *buf)
 
451
static int mbr_bd_read_blocks(bd_srv_t *bd, aoff64_t ba, size_t cnt, void *buf,
 
452
    size_t size)
482
453
{
483
 
        uint64_t gba;
 
454
        part_t *p = bd_srv_part(bd);
 
455
        aoff64_t gba;
 
456
 
 
457
        if (cnt * block_size < size)
 
458
                return EINVAL;
484
459
 
485
460
        if (mbr_bsa_translate(p, ba, cnt, &gba) != EOK)
486
461
                return ELIMIT;
487
462
 
488
 
        return block_read_direct(indef_sid, gba, cnt, buf);
 
463
        return block_read_direct(indev_sid, gba, cnt, buf);
489
464
}
490
465
 
491
466
/** Write blocks to partition. */
492
 
static int mbr_bd_write(part_t *p, uint64_t ba, size_t cnt, const void *buf)
 
467
static int mbr_bd_write_blocks(bd_srv_t *bd, aoff64_t ba, size_t cnt,
 
468
    const void *buf, size_t size)
493
469
{
494
 
        uint64_t gba;
 
470
        part_t *p = bd_srv_part(bd);
 
471
        aoff64_t gba;
 
472
 
 
473
        if (cnt * block_size < size)
 
474
                return EINVAL;
495
475
 
496
476
        if (mbr_bsa_translate(p, ba, cnt, &gba) != EOK)
497
477
                return ELIMIT;
498
478
 
499
 
        return block_write_direct(indef_sid, gba, cnt, buf);
 
479
        return block_write_direct(indev_sid, gba, cnt, buf);
 
480
}
 
481
 
 
482
/** Get device block size. */
 
483
static int mbr_bd_get_block_size(bd_srv_t *bd, size_t *rsize)
 
484
{
 
485
        *rsize = block_size;
 
486
        return EOK;
 
487
}
 
488
 
 
489
/** Get number of blocks on device. */
 
490
static int mbr_bd_get_num_blocks(bd_srv_t *bd, aoff64_t *rnb)
 
491
{
 
492
        part_t *part = bd_srv_part(bd);
 
493
 
 
494
        *rnb = part->length;
 
495
        return EOK;
500
496
}
501
497
 
502
498
/** Translate block segment address with range checking. */