• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 /*
3  * Copyright (C) 2008 The Android Open Source Project
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 #include <stdlib.h>
19 #include <string.h>
20 #include <dirent.h>
21 #include <errno.h>
22 
23 #include <sys/types.h>
24 
25 #include "vold.h"
26 #include "mmc.h"
27 #include "media.h"
28 
29 #define DEBUG_BOOTSTRAP 0
30 
31 static int mmc_bootstrap_controller(char *sysfs_path);
32 static int mmc_bootstrap_card(char *sysfs_path);
33 static int mmc_bootstrap_block(char *devpath);
34 static int mmc_bootstrap_mmcblk(char *devpath);
35 static int mmc_bootstrap_mmcblk_partition(char *devpath);
36 
37 /*
38  * Bootstrap our mmc information.
39  */
mmc_bootstrap()40 int mmc_bootstrap()
41 {
42     DIR *d;
43     struct dirent *de;
44 
45     if (!(d = opendir(SYSFS_CLASS_MMC_PATH))) {
46         LOG_ERROR("Unable to open '%s' (%s)", SYSFS_CLASS_MMC_PATH,
47                   strerror(errno));
48         return -errno;
49     }
50 
51     while ((de = readdir(d))) {
52         char tmp[255];
53 
54         if (de->d_name[0] == '.')
55             continue;
56 
57         sprintf(tmp, "%s/%s", SYSFS_CLASS_MMC_PATH, de->d_name);
58         if (mmc_bootstrap_controller(tmp)) {
59             LOG_ERROR("Error bootstrapping controller '%s' (%s)", tmp,
60                       strerror(errno));
61         }
62     }
63 
64     closedir(d);
65 
66     return 0;
67 }
68 
mmc_bootstrap_controller(char * sysfs_path)69 static int mmc_bootstrap_controller(char *sysfs_path)
70 {
71     DIR *d;
72     struct dirent *de;
73 
74 #if DEBUG_BOOTSTRAP
75     LOG_VOL("bootstrap_controller(%s):", sysfs_path);
76 #endif
77     if (!(d = opendir(sysfs_path))) {
78         LOG_ERROR("Unable to open '%s' (%s)", sysfs_path, strerror(errno));
79         return -errno;
80     }
81 
82     while ((de = readdir(d))) {
83         char tmp[255];
84 
85         if (de->d_name[0] == '.')
86             continue;
87 
88         if ((!strcmp(de->d_name, "uevent")) ||
89             (!strcmp(de->d_name, "subsystem")) ||
90             (!strcmp(de->d_name, "device")) ||
91             (!strcmp(de->d_name, "power"))) {
92             continue;
93         }
94 
95         sprintf(tmp, "%s/%s", sysfs_path, de->d_name);
96 
97         if (mmc_bootstrap_card(tmp) < 0)
98             LOG_ERROR("Error bootstrapping card '%s' (%s)", tmp, strerror(errno));
99     } // while
100 
101     closedir(d);
102     return 0;
103 }
104 
mmc_bootstrap_card(char * sysfs_path)105 static int mmc_bootstrap_card(char *sysfs_path)
106 {
107     char saved_cwd[255];
108     char new_cwd[255];
109     char *devpath;
110     char *uevent_params[4];
111     char *p;
112     char filename[255];
113     char tmp[255];
114     ssize_t sz;
115 
116 #if DEBUG_BOOTSTRAP
117     LOG_VOL("bootstrap_card(%s):", sysfs_path);
118 #endif
119 
120     /*
121      * sysfs_path is based on /sys/class, but we want the actual device class
122      */
123     if (!getcwd(saved_cwd, sizeof(saved_cwd))) {
124         LOGE("Error getting working dir path");
125         return -errno;
126     }
127 
128     if (chdir(sysfs_path) < 0) {
129         LOGE("Unable to chdir to %s (%s)", sysfs_path, strerror(errno));
130         return -errno;
131     }
132 
133     if (!getcwd(new_cwd, sizeof(new_cwd))) {
134         LOGE("Buffer too small for device path");
135         return -errno;
136     }
137 
138     if (chdir(saved_cwd) < 0) {
139         LOGE("Unable to restore working dir");
140         return -errno;
141     }
142 
143     devpath = &new_cwd[4]; // Skip over '/sys'
144 
145     /*
146      * Collect parameters so we can simulate a UEVENT
147      */
148     sprintf(tmp, "DEVPATH=%s", devpath);
149     uevent_params[0] = (char *) strdup(tmp);
150 
151     sprintf(filename, "/sys%s/type", devpath);
152     p = read_file(filename, &sz);
153     p[strlen(p) - 1] = '\0';
154     sprintf(tmp, "MMC_TYPE=%s", p);
155     free(p);
156     uevent_params[1] = (char *) strdup(tmp);
157 
158     sprintf(filename, "/sys%s/name", devpath);
159     p = read_file(filename, &sz);
160     p[strlen(p) - 1] = '\0';
161     sprintf(tmp, "MMC_NAME=%s", p);
162     free(p);
163     uevent_params[2] = (char *) strdup(tmp);
164 
165     uevent_params[3] = (char *) NULL;
166 
167     if (simulate_uevent("mmc", devpath, "add", uevent_params) < 0) {
168         LOGE("Error simulating uevent (%s)", strerror(errno));
169         return -errno;
170     }
171 
172     /*
173      *  Check for block drivers
174      */
175     char block_devpath[255];
176     sprintf(tmp, "%s/block", devpath);
177     sprintf(filename, "/sys%s/block", devpath);
178     if (!access(filename, F_OK)) {
179         if (mmc_bootstrap_block(tmp)) {
180             LOGE("Error bootstrapping block @ %s", tmp);
181         }
182     }
183 
184     return 0;
185 }
186 
mmc_bootstrap_block(char * devpath)187 static int mmc_bootstrap_block(char *devpath)
188 {
189     char blockdir_path[255];
190     DIR *d;
191     struct dirent *de;
192 
193 #if DEBUG_BOOTSTRAP
194     LOG_VOL("mmc_bootstrap_block(%s):", devpath);
195 #endif
196 
197     sprintf(blockdir_path, "/sys%s", devpath);
198 
199     if (!(d = opendir(blockdir_path))) {
200         LOGE("Failed to opendir %s", devpath);
201         return -errno;
202     }
203 
204     while ((de = readdir(d))) {
205         char tmp[255];
206 
207         if (de->d_name[0] == '.')
208             continue;
209         sprintf(tmp, "%s/%s", devpath, de->d_name);
210         if (mmc_bootstrap_mmcblk(tmp))
211             LOGE("Error bootstraping mmcblk @ %s", tmp);
212     }
213     closedir(d);
214     return 0;
215 }
216 
mmc_bootstrap_mmcblk(char * devpath)217 static int mmc_bootstrap_mmcblk(char *devpath)
218 {
219     char *mmcblk_devname;
220     int part_no;
221     int rc;
222 
223 #if DEBUG_BOOTSTRAP
224     LOG_VOL("mmc_bootstrap_mmcblk(%s):", devpath);
225 #endif
226 
227     if ((rc = mmc_bootstrap_mmcblk_partition(devpath))) {
228         LOGE("Error bootstrapping mmcblk partition '%s'", devpath);
229         return rc;
230     }
231 
232     for (mmcblk_devname = &devpath[strlen(devpath)];
233          *mmcblk_devname != '/'; mmcblk_devname--);
234     mmcblk_devname++;
235 
236     for (part_no = 0; part_no < 4; part_no++) {
237         char part_file[255];
238         sprintf(part_file, "/sys%s/%sp%d", devpath, mmcblk_devname, part_no);
239         if (!access(part_file, F_OK)) {
240             char part_devpath[255];
241 
242             sprintf(part_devpath, "%s/%sp%d", devpath, mmcblk_devname, part_no);
243             if (mmc_bootstrap_mmcblk_partition(part_devpath))
244                 LOGE("Error bootstrapping mmcblk partition '%s'", part_devpath);
245         }
246     }
247 
248     return 0;
249 }
250 
mmc_bootstrap_mmcblk_partition(char * devpath)251 static int mmc_bootstrap_mmcblk_partition(char *devpath)
252 {
253     char filename[255];
254     char *uevent_buffer;
255     ssize_t sz;
256     char *uevent_params[4];
257     char tmp[255];
258     FILE *fp;
259     char line[255];
260 
261 #if DEBUG_BOOTSTRAP
262     LOG_VOL("mmc_bootstrap_mmcblk_partition(%s):", devpath);
263 #endif
264 
265     sprintf(tmp, "DEVPATH=%s", devpath);
266     uevent_params[0] = strdup(tmp);
267 
268     sprintf(filename, "/sys%s/uevent", devpath);
269     if (!(fp = fopen(filename, "r"))) {
270         LOGE("Unable to open '%s' (%s)", filename, strerror(errno));
271         return -errno;
272     }
273 
274     while (fgets(line, sizeof(line), fp)) {
275         line[strlen(line)-1] = 0;
276         if (!strncmp(line, "DEVTYPE=", 8))
277             uevent_params[1] = strdup(line);
278         else if (!strncmp(line, "MAJOR=",6))
279             uevent_params[2] = strdup(line);
280         else if (!strncmp(line, "MINOR=",6))
281             uevent_params[3] = strdup(line);
282     }
283     fclose(fp);
284 
285     if (!uevent_params[1] || !uevent_params[2] || !uevent_params[3]) {
286         LOGE("mmcblk uevent missing required params");
287         return -1;
288     }
289     uevent_params[4] = '\0';
290 
291     if (simulate_uevent("block", devpath, "add", uevent_params) < 0) {
292         LOGE("Error simulating uevent (%s)", strerror(errno));
293         return -errno;
294     }
295     return 0;
296 }
297