1 /* 2 * Copyright (C) 2013 Henrik Nordstrom <henrik@henriknordstrom.net> 3 * 4 * SPDX-License-Identifier: GPL-2.0+ 5 */ 6 7 #include <config.h> 8 #include <common.h> 9 #include <part.h> 10 #include <os.h> 11 #include <malloc.h> 12 #include <sandboxblockdev.h> 13 #include <asm/errno.h> 14 15 static struct host_block_dev host_devices[CONFIG_HOST_MAX_DEVICES]; 16 17 static struct host_block_dev *find_host_device(int dev) 18 { 19 if (dev >= 0 && dev < CONFIG_HOST_MAX_DEVICES) 20 return &host_devices[dev]; 21 22 return NULL; 23 } 24 25 static unsigned long host_block_read(block_dev_desc_t *block_dev, 26 unsigned long start, lbaint_t blkcnt, 27 void *buffer) 28 { 29 int dev = block_dev->dev; 30 struct host_block_dev *host_dev = find_host_device(dev); 31 32 if (!host_dev) 33 return -1; 34 if (os_lseek(host_dev->fd, 35 start * host_dev->blk_dev.blksz, 36 OS_SEEK_SET) == -1) { 37 printf("ERROR: Invalid position\n"); 38 return -1; 39 } 40 ssize_t len = os_read(host_dev->fd, buffer, 41 blkcnt * host_dev->blk_dev.blksz); 42 if (len >= 0) 43 return len / host_dev->blk_dev.blksz; 44 return -1; 45 } 46 47 static unsigned long host_block_write(block_dev_desc_t *block_dev, 48 unsigned long start, lbaint_t blkcnt, 49 const void *buffer) 50 { 51 int dev = block_dev->dev; 52 struct host_block_dev *host_dev = find_host_device(dev); 53 if (os_lseek(host_dev->fd, 54 start * host_dev->blk_dev.blksz, 55 OS_SEEK_SET) == -1) { 56 printf("ERROR: Invalid position\n"); 57 return -1; 58 } 59 ssize_t len = os_write(host_dev->fd, buffer, blkcnt * 60 host_dev->blk_dev.blksz); 61 if (len >= 0) 62 return len / host_dev->blk_dev.blksz; 63 return -1; 64 } 65 66 int host_dev_bind(int dev, char *filename) 67 { 68 struct host_block_dev *host_dev = find_host_device(dev); 69 70 if (!host_dev) 71 return -1; 72 if (host_dev->blk_dev.priv) { 73 os_close(host_dev->fd); 74 host_dev->blk_dev.priv = NULL; 75 } 76 if (host_dev->filename) 77 free(host_dev->filename); 78 if (filename && *filename) { 79 host_dev->filename = strdup(filename); 80 } else { 81 host_dev->filename = NULL; 82 return 0; 83 } 84 85 host_dev->fd = os_open(host_dev->filename, OS_O_RDWR); 86 if (host_dev->fd == -1) { 87 printf("Failed to access host backing file '%s'\n", 88 host_dev->filename); 89 return 1; 90 } 91 92 block_dev_desc_t *blk_dev = &host_dev->blk_dev; 93 blk_dev->if_type = IF_TYPE_HOST; 94 blk_dev->priv = host_dev; 95 blk_dev->blksz = 512; 96 blk_dev->lba = os_lseek(host_dev->fd, 0, OS_SEEK_END) / blk_dev->blksz; 97 blk_dev->block_read = host_block_read; 98 blk_dev->block_write = host_block_write; 99 blk_dev->dev = dev; 100 blk_dev->part_type = PART_TYPE_UNKNOWN; 101 init_part(blk_dev); 102 103 return 0; 104 } 105 106 int host_get_dev_err(int dev, block_dev_desc_t **blk_devp) 107 { 108 struct host_block_dev *host_dev = find_host_device(dev); 109 110 if (!host_dev) 111 return -ENODEV; 112 113 if (!host_dev->blk_dev.priv) 114 return -ENOENT; 115 116 *blk_devp = &host_dev->blk_dev; 117 return 0; 118 } 119 120 block_dev_desc_t *host_get_dev(int dev) 121 { 122 block_dev_desc_t *blk_dev; 123 124 if (host_get_dev_err(dev, &blk_dev)) 125 return NULL; 126 127 return blk_dev; 128 } 129