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(int dev, unsigned long start, 26 lbaint_t blkcnt, void *buffer) 27 { 28 struct host_block_dev *host_dev = find_host_device(dev); 29 30 if (!host_dev) 31 return -1; 32 if (os_lseek(host_dev->fd, 33 start * host_dev->blk_dev.blksz, 34 OS_SEEK_SET) == -1) { 35 printf("ERROR: Invalid position\n"); 36 return -1; 37 } 38 ssize_t len = os_read(host_dev->fd, buffer, 39 blkcnt * host_dev->blk_dev.blksz); 40 if (len >= 0) 41 return len / host_dev->blk_dev.blksz; 42 return -1; 43 } 44 45 static unsigned long host_block_write(int dev, unsigned long start, 46 lbaint_t blkcnt, const void *buffer) 47 { 48 struct host_block_dev *host_dev = find_host_device(dev); 49 if (os_lseek(host_dev->fd, 50 start * host_dev->blk_dev.blksz, 51 OS_SEEK_SET) == -1) { 52 printf("ERROR: Invalid position\n"); 53 return -1; 54 } 55 ssize_t len = os_write(host_dev->fd, buffer, blkcnt * 56 host_dev->blk_dev.blksz); 57 if (len >= 0) 58 return len / host_dev->blk_dev.blksz; 59 return -1; 60 } 61 62 int host_dev_bind(int dev, char *filename) 63 { 64 struct host_block_dev *host_dev = find_host_device(dev); 65 66 if (!host_dev) 67 return -1; 68 if (host_dev->blk_dev.priv) { 69 os_close(host_dev->fd); 70 host_dev->blk_dev.priv = NULL; 71 } 72 if (host_dev->filename) 73 free(host_dev->filename); 74 if (filename && *filename) { 75 host_dev->filename = strdup(filename); 76 } else { 77 host_dev->filename = NULL; 78 return 0; 79 } 80 81 host_dev->fd = os_open(host_dev->filename, OS_O_RDWR); 82 if (host_dev->fd == -1) { 83 printf("Failed to access host backing file '%s'\n", 84 host_dev->filename); 85 return 1; 86 } 87 88 block_dev_desc_t *blk_dev = &host_dev->blk_dev; 89 blk_dev->if_type = IF_TYPE_HOST; 90 blk_dev->priv = host_dev; 91 blk_dev->blksz = 512; 92 blk_dev->lba = os_lseek(host_dev->fd, 0, OS_SEEK_END) / blk_dev->blksz; 93 blk_dev->block_read = host_block_read; 94 blk_dev->block_write = host_block_write; 95 blk_dev->dev = dev; 96 blk_dev->part_type = PART_TYPE_UNKNOWN; 97 init_part(blk_dev); 98 99 return 0; 100 } 101 102 int host_get_dev_err(int dev, block_dev_desc_t **blk_devp) 103 { 104 struct host_block_dev *host_dev = find_host_device(dev); 105 106 if (!host_dev) 107 return -ENODEV; 108 109 if (!host_dev->blk_dev.priv) 110 return -ENOENT; 111 112 *blk_devp = &host_dev->blk_dev; 113 return 0; 114 } 115 116 block_dev_desc_t *host_get_dev(int dev) 117 { 118 block_dev_desc_t *blk_dev; 119 120 if (host_get_dev_err(dev, &blk_dev)) 121 return NULL; 122 123 return blk_dev; 124 } 125