]> Git Repo - J-u-boot.git/blob - drivers/block/host_dev.c
Subtree merge tag 'v6.9-dts' of devicetree-rebasing repo [1] into dts/upstream
[J-u-boot.git] / drivers / block / host_dev.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Driver for sandbox host interface, used to access files on the host which
4  * contain partitions and filesystem
5  *
6  * Copyright 2022 Google LLC
7  * Written by Simon Glass <[email protected]>
8  */
9
10 #define LOG_CATEGORY UCLASS_HOST
11
12 #include <blk.h>
13 #include <bootdev.h>
14 #include <dm.h>
15 #include <log.h>
16 #include <malloc.h>
17 #include <os.h>
18 #include <sandbox_host.h>
19 #include <dm/device-internal.h>
20
21 static int host_sb_attach_file(struct udevice *dev, const char *filename)
22 {
23         struct host_sb_plat *plat = dev_get_plat(dev);
24         struct blk_desc *desc;
25         struct udevice *blk;
26         int ret, fd;
27         off_t size;
28         char *fname;
29
30         if (!filename)
31                 return -EINVAL;
32
33         if (plat->fd)
34                 return log_msg_ret("fd", -EEXIST);
35
36         /* Sanity check that host_sb_bind() has been used */
37         ret = blk_find_from_parent(dev, &blk);
38         if (ret)
39                 return ret;
40
41         fd = os_open(filename, OS_O_RDWR);
42         if (fd == -1) {
43                 printf("Failed to access host backing file '%s', trying read-only\n",
44                        filename);
45                 fd = os_open(filename, OS_O_RDONLY);
46                 if (fd == -1) {
47                         printf("- still failed\n");
48                         return log_msg_ret("open", -ENOENT);
49                 }
50         }
51
52         fname = strdup(filename);
53         if (!fname) {
54                 ret = -ENOMEM;
55                 goto err_fname;
56         }
57
58         size = os_filesize(fd);
59         desc = dev_get_uclass_plat(blk);
60         if (size % desc->blksz) {
61                 printf("The size of host backing file '%s' is not multiple of "
62                        "the device block size\n", filename);
63                 ret = -EINVAL;
64                 goto err_fname;
65         }
66         desc->lba = size / desc->blksz;
67
68         /* write this in last, when nothing can go wrong */
69         plat = dev_get_plat(dev);
70         plat->fd = fd;
71         plat->filename = fname;
72
73         return 0;
74
75 err_fname:
76         os_close(fd);
77
78         return ret;
79 }
80
81 static int host_sb_detach_file(struct udevice *dev)
82 {
83         struct host_sb_plat *plat = dev_get_plat(dev);
84         int ret;
85
86         if (!plat->fd)
87                 return log_msg_ret("fd", -ENOENT);
88
89         ret = device_remove(dev, DM_REMOVE_NORMAL);
90         if (ret)
91                 return log_msg_ret("rem", ret);
92
93         /* Unbind all children */
94         ret = device_chld_unbind(dev, NULL);
95         if (ret)
96                 return log_msg_ret("unb", ret);
97
98         os_close(plat->fd);
99         plat->fd = 0;
100         free(plat->filename);
101         free(plat->label);
102
103         return 0;
104 }
105
106 static int host_sb_bind(struct udevice *dev)
107 {
108         struct udevice *blk, *bdev;
109         struct blk_desc *desc;
110         int ret;
111
112         ret = blk_create_devicef(dev, "sandbox_host_blk", "blk", UCLASS_HOST,
113                                  dev_seq(dev), DEFAULT_BLKSZ, 0, &blk);
114         if (ret)
115                 return log_msg_ret("blk", ret);
116
117         desc = dev_get_uclass_plat(blk);
118         snprintf(desc->vendor, BLK_VEN_SIZE, "U-Boot");
119         snprintf(desc->product, BLK_PRD_SIZE, "hostfile");
120         snprintf(desc->revision, BLK_REV_SIZE, "1.0");
121
122         if (CONFIG_IS_ENABLED(BOOTSTD)) {
123                 ret = bootdev_bind(dev, "host_bootdev", "bootdev", &bdev);
124                 if (ret)
125                         return log_msg_ret("bd", ret);
126         }
127
128         return 0;
129 }
130
131 static struct host_ops host_sb_ops = {
132         .attach_file    = host_sb_attach_file,
133         .detach_file    = host_sb_detach_file,
134 };
135
136 static const struct udevice_id host_ids[] = {
137         { .compatible = "sandbox,host" },
138         { }
139 };
140
141 U_BOOT_DRIVER(host_sb_drv) = {
142         .name           = "host_sb_drv",
143         .id             = UCLASS_HOST,
144         .of_match       = host_ids,
145         .ops            = &host_sb_ops,
146         .bind           = host_sb_bind,
147         .plat_auto      = sizeof(struct host_sb_plat),
148 };
This page took 0.034744 seconds and 4 git commands to generate.