1 /****************************************************************************
2 * drivers/bch/bchlib_setup.c
3 *
4 * Licensed to the Apache Software Foundation (ASF) under one or more
5 * contributor license agreements. See the NOTICE file distributed with
6 * this work for additional information regarding copyright ownership. The
7 * ASF licenses this file to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance with the
9 * License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
16 * License for the specific language governing permissions and limitations
17 * under the License.
18 *
19 ****************************************************************************/
20
21 /****************************************************************************
22 * Included Files
23 ****************************************************************************/
24 #include <sys/types.h>
25 #include <sys/mount.h>
26 #include <stdint.h>
27 #include <stdbool.h>
28 #include <stdlib.h>
29 #include <errno.h>
30 #include <assert.h>
31 #include <securec.h>
32 #include "bch.h"
33
34 /****************************************************************************
35 * Public Functions
36 ****************************************************************************/
37
38 /****************************************************************************
39 * Name: bchlib_setup
40 *
41 * Description:
42 * Setup so that the block driver referenced by 'blkdev' can be accessed
43 * similar to a character device.
44 *
45 ****************************************************************************/
46
bchlib_setup(const char * blkdev,bool readonly,void ** handle)47 int bchlib_setup(const char *blkdev, bool readonly, void **handle)
48 {
49 struct bchlib_s *bch;
50 struct geometry geo;
51 los_part *part;
52 int ret;
53
54 DEBUGASSERT(blkdev);
55
56 /* Allocate the BCH state structure */
57
58 bch = (struct bchlib_s *)zalloc(sizeof(struct bchlib_s));
59 if (!bch)
60 {
61 PRINTK("ERROR: Failed to allocate BCH structure\n");
62 return -ENOMEM;
63 }
64
65 /* Open the block driver */
66
67 ret = open_blockdriver(blkdev, readonly ? MS_RDONLY : 0, &bch->vnode);
68 if (ret < 0)
69 {
70 PRINTK("ERROR: Failed to open driver %s: %d\n", blkdev, -ret);
71 goto errout_with_bch;
72 }
73
74 struct drv_data *drv = (struct drv_data *)bch->vnode->data;
75 struct block_operations *bops = (struct block_operations *)drv->ops;
76
77 DEBUGASSERT(bch->vnode && bops && bops->geometry);
78
79 ret = bops->geometry(bch->vnode, &geo);
80 if (ret < 0)
81 {
82 PRINTK("ERROR: geometry failed: %d\n", -ret);
83 goto errout_with_bch;
84 }
85
86 if (!geo.geo_available)
87 {
88 PRINTK("ERROR: geometry failed: %d\n", -ret);
89 ret = -ENODEV;
90 goto errout_with_bch;
91 }
92
93 if (!readonly && (!bops->write || !geo.geo_writeenabled))
94 {
95 PRINTK("ERROR: write access not supported\n");
96 ret = -EACCES;
97 goto errout_with_bch;
98 }
99
100 /* Save the geometry info and complete initialization of the structure */
101
102 (void)sem_init(&bch->sem, 0, 1);
103 bch->nsectors = geo.geo_nsectors;
104 bch->sectsize = geo.geo_sectorsize;
105 bch->sector = (size_t)-1;
106 bch->readonly = readonly;
107 bch->dirty = false;
108 bch->unlinked = false;
109
110 part = los_part_find(bch->vnode);
111 if (part != NULL)
112 {
113 bch->sectstart = part->sector_start;
114 bch->nsectors = part->sector_count;
115 bch->disk = get_disk(part->disk_id);
116 }
117 else
118 {
119 PRINTK("ERROR: los_part_find failed\n");
120 ret = -ENODEV;
121 goto errout_with_bch;
122 }
123
124 /* Allocate the sector I/O buffer */
125
126 bch->buffer = (uint8_t *)malloc(bch->sectsize);
127 if (!bch->buffer)
128 {
129 PRINTK("ERROR: Failed to allocate sector buffer\n");
130 ret = -ENOMEM;
131 goto errout_with_bch;
132 }
133
134 *handle = bch;
135 return OK;
136
137 errout_with_bch:
138 (void)sem_destroy(&bch->sem);
139 free(bch);
140 return ret;
141 }
142