1 /*
2  * Copyright (c) 2010 Travis Geiselbrecht
3  *
4  * Use of this source code is governed by a MIT-style
5  * license that can be found in the LICENSE file or at
6  * https://opensource.org/licenses/MIT
7  */
8 #include <lk/err.h>
9 #include <lk/debug.h>
10 #include <lk/trace.h>
11 #include <platform.h>
12 #include "platform_p.h"
13 #include <platform/armemu.h>
14 #include <lib/bio.h>
15 #include <lk/reg.h>
16 
get_blkdev_len(void)17 static uint64_t get_blkdev_len(void) {
18     return *REG64(BDEV_LEN);
19 }
20 
read_block(struct bdev * dev,void * buf,bnum_t block,uint count)21 ssize_t read_block(struct bdev *dev, void *buf, bnum_t block, uint count) {
22     /* assume args have been validated by layer above */
23     *REG32(BDEV_CMD_ADDR) = (uint32_t)buf;
24     *REG64(BDEV_CMD_OFF) = (uint64_t)((uint64_t)block * dev->block_size);
25     *REG32(BDEV_CMD_LEN) = count * dev->block_size;
26 
27     *REG32(BDEV_CMD) = BDEV_CMD_READ;
28 
29     uint32_t err = *REG32(BDEV_CMD) & BDEV_CMD_ERRMASK;
30     if (err == BDEV_CMD_ERR_NONE)
31         return count * dev->block_size;
32     else
33         return ERR_IO;
34 }
35 
write_block(struct bdev * dev,const void * buf,bnum_t block,uint count)36 ssize_t write_block(struct bdev *dev, const void *buf, bnum_t block, uint count) {
37     /* assume args have been validated by layer above */
38     *REG32(BDEV_CMD_ADDR) = (uint32_t)buf;
39     *REG64(BDEV_CMD_OFF) = (uint64_t)((uint64_t)block * dev->block_size);
40     *REG32(BDEV_CMD_LEN) = count * dev->block_size;
41 
42     *REG32(BDEV_CMD) = BDEV_CMD_WRITE;
43 
44     uint32_t err = *REG32(BDEV_CMD) & BDEV_CMD_ERRMASK;
45     if (err == BDEV_CMD_ERR_NONE)
46         return count * dev->block_size;
47     else
48         return ERR_IO;
49 }
50 
platform_init_blkdev(void)51 void platform_init_blkdev(void) {
52     static bdev_t dev;
53 
54     if ((*REG32(SYSINFO_FEATURES) & SYSINFO_FEATURE_BLOCKDEV) == 0)
55         return; // no block device
56 
57     TRACEF("device len %lld\n", get_blkdev_len());
58 
59     if (get_blkdev_len() == 0)
60         return;
61 
62     bio_initialize_bdev(&dev, "block0", 512, get_blkdev_len() / 512, 0, NULL,
63                         BIO_FLAGS_NONE);
64 
65     // fill in hooks
66     dev.read_block = &read_block;
67     dev.write_block = &write_block;
68 
69     bio_register_device(&dev);
70 }
71 
72