2 * Copyright (C) 2013 Henrik Nordstrom <henrik@henriknordstrom.net>
4 * SPDX-License-Identifier: GPL-2.0+
14 #include <sandboxblockdev.h>
15 #include <linux/errno.h>
16 #include <dm/device-internal.h>
18 DECLARE_GLOBAL_DATA_PTR
;
21 static struct host_block_dev host_devices
[CONFIG_HOST_MAX_DEVICES
];
23 static struct host_block_dev
*find_host_device(int dev
)
25 if (dev
>= 0 && dev
< CONFIG_HOST_MAX_DEVICES
)
26 return &host_devices
[dev
];
33 static unsigned long host_block_read(struct udevice
*dev
,
34 unsigned long start
, lbaint_t blkcnt
,
37 struct host_block_dev
*host_dev
= dev_get_priv(dev
);
38 struct blk_desc
*block_dev
= dev_get_uclass_platdata(dev
);
41 static unsigned long host_block_read(struct blk_desc
*block_dev
,
42 unsigned long start
, lbaint_t blkcnt
,
45 int dev
= block_dev
->devnum
;
46 struct host_block_dev
*host_dev
= find_host_device(dev
);
52 if (os_lseek(host_dev
->fd
, start
* block_dev
->blksz
, OS_SEEK_SET
) ==
54 printf("ERROR: Invalid block %lx\n", start
);
57 ssize_t len
= os_read(host_dev
->fd
, buffer
, blkcnt
* block_dev
->blksz
);
59 return len
/ block_dev
->blksz
;
64 static unsigned long host_block_write(struct udevice
*dev
,
65 unsigned long start
, lbaint_t blkcnt
,
68 struct host_block_dev
*host_dev
= dev_get_priv(dev
);
69 struct blk_desc
*block_dev
= dev_get_uclass_platdata(dev
);
71 static unsigned long host_block_write(struct blk_desc
*block_dev
,
72 unsigned long start
, lbaint_t blkcnt
,
75 int dev
= block_dev
->devnum
;
76 struct host_block_dev
*host_dev
= find_host_device(dev
);
79 if (os_lseek(host_dev
->fd
, start
* block_dev
->blksz
, OS_SEEK_SET
) ==
81 printf("ERROR: Invalid block %lx\n", start
);
84 ssize_t len
= os_write(host_dev
->fd
, buffer
, blkcnt
* block_dev
->blksz
);
86 return len
/ block_dev
->blksz
;
91 int host_dev_bind(int devnum
, char *filename
)
93 struct host_block_dev
*host_dev
;
95 char dev_name
[20], *str
, *fname
;
98 /* Remove and unbind the old device, if any */
99 ret
= blk_get_device(IF_TYPE_HOST
, devnum
, &dev
);
101 ret
= device_remove(dev
, DM_REMOVE_NORMAL
);
104 ret
= device_unbind(dev
);
107 } else if (ret
!= -ENODEV
) {
114 snprintf(dev_name
, sizeof(dev_name
), "host%d", devnum
);
115 str
= strdup(dev_name
);
118 fname
= strdup(filename
);
124 fd
= os_open(filename
, OS_O_RDWR
);
126 printf("Failed to access host backing file '%s'\n", filename
);
130 ret
= blk_create_device(gd
->dm_root
, "sandbox_host_blk", str
,
131 IF_TYPE_HOST
, devnum
, 512,
132 os_lseek(fd
, 0, OS_SEEK_END
) / 512, &dev
);
135 ret
= device_probe(dev
);
141 host_dev
= dev_get_priv(dev
);
143 host_dev
->filename
= fname
;
145 return blk_prepare_device(dev
);
154 int host_dev_bind(int dev
, char *filename
)
156 struct host_block_dev
*host_dev
= find_host_device(dev
);
160 if (host_dev
->blk_dev
.priv
) {
161 os_close(host_dev
->fd
);
162 host_dev
->blk_dev
.priv
= NULL
;
164 if (host_dev
->filename
)
165 free(host_dev
->filename
);
166 if (filename
&& *filename
) {
167 host_dev
->filename
= strdup(filename
);
169 host_dev
->filename
= NULL
;
173 host_dev
->fd
= os_open(host_dev
->filename
, OS_O_RDWR
);
174 if (host_dev
->fd
== -1) {
175 printf("Failed to access host backing file '%s'\n",
180 struct blk_desc
*blk_dev
= &host_dev
->blk_dev
;
181 blk_dev
->if_type
= IF_TYPE_HOST
;
182 blk_dev
->priv
= host_dev
;
183 blk_dev
->blksz
= 512;
184 blk_dev
->lba
= os_lseek(host_dev
->fd
, 0, OS_SEEK_END
) / blk_dev
->blksz
;
185 blk_dev
->block_read
= host_block_read
;
186 blk_dev
->block_write
= host_block_write
;
187 blk_dev
->devnum
= dev
;
188 blk_dev
->part_type
= PART_TYPE_UNKNOWN
;
195 int host_get_dev_err(int devnum
, struct blk_desc
**blk_devp
)
201 ret
= blk_get_device(IF_TYPE_HOST
, devnum
, &dev
);
204 *blk_devp
= dev_get_uclass_platdata(dev
);
206 struct host_block_dev
*host_dev
= find_host_device(devnum
);
211 if (!host_dev
->blk_dev
.priv
)
214 *blk_devp
= &host_dev
->blk_dev
;
221 static const struct blk_ops sandbox_host_blk_ops
= {
222 .read
= host_block_read
,
223 .write
= host_block_write
,
226 U_BOOT_DRIVER(sandbox_host_blk
) = {
227 .name
= "sandbox_host_blk",
229 .ops
= &sandbox_host_blk_ops
,
230 .priv_auto_alloc_size
= sizeof(struct host_block_dev
),
233 U_BOOT_LEGACY_BLK(sandbox_host
) = {
234 .if_typename
= "host",
235 .if_type
= IF_TYPE_HOST
,
236 .max_devs
= CONFIG_HOST_MAX_DEVICES
,
237 .get_dev
= host_get_dev_err
,