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