blob: 492dadcdac43188a99570ad1e5d5447ce60ea707 [file] [log] [blame]
Shashank Mittal815ca5d2010-07-27 11:09:19 -07001/*
2 * Copyright (c) 2010, Code Aurora Forum. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above
10 * copyright notice, this list of conditions and the following
11 * disclaimer in the documentation and/or other materials provided
12 * with the distribution.
13 * * Neither the name of Code Aurora Forum, Inc. nor the names of its
14 * contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30#include <stdlib.h>
31#include <stdio.h>
32#include <unistd.h>
33#include <dirent.h>
34#include <string.h>
35#include <errno.h>
36#include <sys/types.h>
37#include <sys/reboot.h>
38#include <sys/stat.h>
39#include <sys/wait.h>
40#include <sys/mount.h> // for _IOW, _IOR, mount()
41
42#include "mmcutils.h"
43
44unsigned ext3_count = 0;
45char *ext3_partitions[] = {"system", "userdata", "cache", "NONE"};
46
47unsigned vfat_count = 0;
48char *vfat_partitions[] = {"modem", "NONE"};
49
Koushik Dutta19447c02010-11-10 10:40:44 -080050struct MmcPartition {
51 char *device_index;
52 char *filesystem;
53 char *name;
54 unsigned dstatus;
55 unsigned dtype ;
56 unsigned dfirstsec;
57 unsigned dsize;
58};
59
Shashank Mittal815ca5d2010-07-27 11:09:19 -070060typedef struct {
61 MmcPartition *partitions;
62 int partitions_allocd;
63 int partition_count;
64} MmcState;
65
66static MmcState g_mmc_state = {
67 NULL, // partitions
68 0, // partitions_allocd
69 -1 // partition_count
70};
71
72#define MMC_DEVICENAME "/dev/block/mmcblk0"
73
74static void
75mmc_partition_name (MmcPartition *mbr, unsigned int type) {
76 switch(type)
77 {
78 char name[64];
79 case MMC_BOOT_TYPE:
80 sprintf(name,"boot");
81 mbr->name = strdup(name);
82 break;
Koushik Duttafef77c02010-11-09 20:03:42 -080083 case MMC_RECOVERY_TYPE:
84 sprintf(name,"recovery");
85 mbr->name = strdup(name);
86 break;
Shashank Mittal815ca5d2010-07-27 11:09:19 -070087 case MMC_EXT3_TYPE:
88 if (strcmp("NONE", ext3_partitions[ext3_count])) {
89 strcpy((char *)name,(const char *)ext3_partitions[ext3_count]);
90 mbr->name = strdup(name);
91 ext3_count++;
92 }
93 mbr->filesystem = strdup("ext3");
94 break;
95 case MMC_VFAT_TYPE:
96 if (strcmp("NONE", vfat_partitions[vfat_count])) {
97 strcpy((char *)name,(const char *)vfat_partitions[vfat_count]);
98 mbr->name = strdup(name);
99 vfat_count++;
100 }
101 mbr->filesystem = strdup("vfat");
102 break;
103 };
104}
105
106static int
107mmc_read_mbr (const char *device, MmcPartition *mbr) {
108 FILE *fd;
109 unsigned char buffer[512];
110 int idx, i;
111 unsigned mmc_partition_count = 0;
112 unsigned int dtype;
113 unsigned int dfirstsec;
114 unsigned int EBR_first_sec;
115 unsigned int EBR_current_sec;
116 int ret = -1;
117
118 fd = fopen(device, "r");
119 if(fd == NULL)
120 {
121 printf("Can't open device: \"%s\"\n", device);
122 goto ERROR2;
123 }
124 if ((fread(buffer, 512, 1, fd)) != 1)
125 {
126 printf("Can't read device: \"%s\"\n", device);
127 goto ERROR1;
128 }
129 /* Check to see if signature exists */
130 if ((buffer[TABLE_SIGNATURE] != 0x55) || \
131 (buffer[TABLE_SIGNATURE + 1] != 0xAA))
132 {
133 printf("Incorrect mbr signatures!\n");
134 goto ERROR1;
135 }
136 idx = TABLE_ENTRY_0;
137 for (i = 0; i < 4; i++)
138 {
139 char device_index[128];
140
141 mbr[mmc_partition_count].dstatus = \
142 buffer[idx + i * TABLE_ENTRY_SIZE + OFFSET_STATUS];
143 mbr[mmc_partition_count].dtype = \
144 buffer[idx + i * TABLE_ENTRY_SIZE + OFFSET_TYPE];
145 mbr[mmc_partition_count].dfirstsec = \
146 GET_LWORD_FROM_BYTE(&buffer[idx + \
147 i * TABLE_ENTRY_SIZE + \
148 OFFSET_FIRST_SEC]);
149 mbr[mmc_partition_count].dsize = \
150 GET_LWORD_FROM_BYTE(&buffer[idx + \
151 i * TABLE_ENTRY_SIZE + \
152 OFFSET_SIZE]);
153 dtype = mbr[mmc_partition_count].dtype;
154 dfirstsec = mbr[mmc_partition_count].dfirstsec;
155 mmc_partition_name(&mbr[mmc_partition_count], \
156 mbr[mmc_partition_count].dtype);
157
158 sprintf(device_index, "%sp%d", device, (mmc_partition_count+1));
159 mbr[mmc_partition_count].device_index = strdup(device_index);
160
161 mmc_partition_count++;
162 if (mmc_partition_count == MAX_PARTITIONS)
163 goto SUCCESS;
164 }
165
166 /* See if the last partition is EBR, if not, parsing is done */
167 if (dtype != 0x05)
168 {
169 goto SUCCESS;
170 }
171
172 EBR_first_sec = dfirstsec;
173 EBR_current_sec = dfirstsec;
174
175 fseek (fd, (EBR_first_sec * 512), SEEK_SET);
176 if ((fread(buffer, 512, 1, fd)) != 1)
177 goto ERROR1;
178
179 /* Loop to parse the EBR */
180 for (i = 0;; i++)
181 {
182 char device_index[128];
183
184 if ((buffer[TABLE_SIGNATURE] != 0x55) || (buffer[TABLE_SIGNATURE + 1] != 0xAA))
185 {
186 break;
187 }
188 mbr[mmc_partition_count].dstatus = \
189 buffer[TABLE_ENTRY_0 + OFFSET_STATUS];
190 mbr[mmc_partition_count].dtype = \
191 buffer[TABLE_ENTRY_0 + OFFSET_TYPE];
192 mbr[mmc_partition_count].dfirstsec = \
193 GET_LWORD_FROM_BYTE(&buffer[TABLE_ENTRY_0 + \
194 OFFSET_FIRST_SEC]) + \
195 EBR_current_sec;
196 mbr[mmc_partition_count].dsize = \
197 GET_LWORD_FROM_BYTE(&buffer[TABLE_ENTRY_0 + \
198 OFFSET_SIZE]);
199 mmc_partition_name(&mbr[mmc_partition_count], \
200 mbr[mmc_partition_count].dtype);
201
202 sprintf(device_index, "%sp%d", device, (mmc_partition_count+1));
203 mbr[mmc_partition_count].device_index = strdup(device_index);
204
205 mmc_partition_count++;
206 if (mmc_partition_count == MAX_PARTITIONS)
207 goto SUCCESS;
208
209 dfirstsec = GET_LWORD_FROM_BYTE(&buffer[TABLE_ENTRY_1 + OFFSET_FIRST_SEC]);
210 if(dfirstsec == 0)
211 {
212 /* Getting to the end of the EBR tables */
213 break;
214 }
215 /* More EBR to follow - read in the next EBR sector */
216 fseek (fd, ((EBR_first_sec + dfirstsec) * 512), SEEK_SET);
217 if ((fread(buffer, 512, 1, fd)) != 1)
218 goto ERROR1;
219
220 EBR_current_sec = EBR_first_sec + dfirstsec;
221 }
222
223SUCCESS:
224 ret = mmc_partition_count;
225ERROR1:
226 fclose(fd);
227ERROR2:
228 return ret;
229}
230
231int
232mmc_scan_partitions() {
233 int i;
234 ssize_t nbytes;
235
236 if (g_mmc_state.partitions == NULL) {
237 const int nump = MAX_PARTITIONS;
238 MmcPartition *partitions = malloc(nump * sizeof(*partitions));
239 if (partitions == NULL) {
240 errno = ENOMEM;
241 return -1;
242 }
243 g_mmc_state.partitions = partitions;
244 g_mmc_state.partitions_allocd = nump;
245 memset(partitions, 0, nump * sizeof(*partitions));
246 }
247 g_mmc_state.partition_count = 0;
248 ext3_count = 0;
249 vfat_count = 0;
250
251 /* Initialize all of the entries to make things easier later.
252 * (Lets us handle sparsely-numbered partitions, which
253 * may not even be possible.)
254 */
255 for (i = 0; i < g_mmc_state.partitions_allocd; i++) {
256 MmcPartition *p = &g_mmc_state.partitions[i];
257 if (p->device_index != NULL) {
258 free(p->device_index);
259 p->device_index = NULL;
260 }
261 if (p->name != NULL) {
262 free(p->name);
263 p->name = NULL;
264 }
265 if (p->filesystem != NULL) {
266 free(p->filesystem);
267 p->filesystem = NULL;
268 }
269 }
270
271 g_mmc_state.partition_count = mmc_read_mbr(MMC_DEVICENAME, g_mmc_state.partitions);
272 if(g_mmc_state.partition_count == -1)
273 {
274 printf("Error in reading mbr!\n");
275 // keep "partitions" around so we can free the names on a rescan.
276 g_mmc_state.partition_count = -1;
277 }
278 return g_mmc_state.partition_count;
279}
280
Christopher Lais066a1022011-01-16 06:02:34 -0600281static const MmcPartition *
282mmc_find_partition_by_device_index(const char *device_index)
283{
284 if (g_mmc_state.partitions != NULL) {
285 int i;
286 for (i = 0; i < g_mmc_state.partitions_allocd; i++) {
287 MmcPartition *p = &g_mmc_state.partitions[i];
288 if (p->device_index !=NULL && p->name != NULL) {
289 if (strcmp(p->device_index, device_index) == 0) {
290 return p;
291 }
292 }
293 }
294 }
295 return NULL;
296}
297
Shashank Mittal815ca5d2010-07-27 11:09:19 -0700298const MmcPartition *
299mmc_find_partition_by_name(const char *name)
300{
Christopher Lais066a1022011-01-16 06:02:34 -0600301 if (name[0] == '/') {
302 return mmc_find_partition_by_device_index(name);
303 }
304
Shashank Mittal815ca5d2010-07-27 11:09:19 -0700305 if (g_mmc_state.partitions != NULL) {
306 int i;
307 for (i = 0; i < g_mmc_state.partitions_allocd; i++) {
308 MmcPartition *p = &g_mmc_state.partitions[i];
309 if (p->device_index !=NULL && p->name != NULL) {
310 if (strcmp(p->name, name) == 0) {
311 return p;
312 }
313 }
314 }
315 }
316 return NULL;
317}
318
Koushik Duttafef77c02010-11-09 20:03:42 -0800319#define MKE2FS_BIN "/sbin/mke2fs"
320#define TUNE2FS_BIN "/sbin/tune2fs"
321#define E2FSCK_BIN "/sbin/e2fsck"
Shashank Mittal815ca5d2010-07-27 11:09:19 -0700322
Koushik Duttada32b542011-01-01 17:55:22 -0800323int
Shashank Mittal815ca5d2010-07-27 11:09:19 -0700324run_exec_process ( char **argv) {
325 pid_t pid;
326 int status;
327 pid = fork();
328 if (pid == 0) {
329 execv(argv[0], argv);
330 fprintf(stderr, "E:Can't run (%s)\n",strerror(errno));
331 _exit(-1);
332 }
333
334 waitpid(pid, &status, 0);
335 if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
336 return 1;
337 }
338 return 0;
339}
340
341int
Koushik Duttab4c5fd62011-01-02 22:54:31 -0800342format_ext3_device (const char *device) {
Koushik Dutta47591ce2011-06-27 17:52:25 -0700343#ifdef BOARD_HAS_LARGE_FILESYSTEM
Tony Layher6d19f222011-03-20 08:28:09 -0400344 char *const mke2fs[] = {MKE2FS_BIN, "-j", "-q", device, NULL};
Koushik Duttafaa477e2011-03-20 15:44:48 -0700345 char *const tune2fs[] = {TUNE2FS_BIN, "-C", "1", device, NULL};
346#else
347 char *const mke2fs[] = {MKE2FS_BIN, "-j", device, NULL};
348 char *const tune2fs[] = {TUNE2FS_BIN, "-j", "-C", "1", device, NULL};
349#endif
350 // Run mke2fs
Koushik Duttabf5a60a2011-08-31 23:28:21 -0700351 if(run_exec_process(mke2fs)) {
352 printf("failure while running mke2fs\n");
Shashank Mittal815ca5d2010-07-27 11:09:19 -0700353 return -1;
Koushik Duttabf5a60a2011-08-31 23:28:21 -0700354 }
Shashank Mittal815ca5d2010-07-27 11:09:19 -0700355
356 // Run tune2fs
Koushik Duttabf5a60a2011-08-31 23:28:21 -0700357 if(run_exec_process(tune2fs)) {
358 printf("failure while running mke2fs\n");
Shashank Mittal815ca5d2010-07-27 11:09:19 -0700359 return -1;
Koushik Duttabf5a60a2011-08-31 23:28:21 -0700360 }
Shashank Mittal815ca5d2010-07-27 11:09:19 -0700361
362 // Run e2fsck
363 char *const e2fsck[] = {E2FSCK_BIN, "-fy", device, NULL};
Koushik Duttabf5a60a2011-08-31 23:28:21 -0700364 if(run_exec_process(e2fsck)) {
365 printf("failure while running e2fsck\n");
Shashank Mittal815ca5d2010-07-27 11:09:19 -0700366 return -1;
Koushik Duttabf5a60a2011-08-31 23:28:21 -0700367 }
Shashank Mittal815ca5d2010-07-27 11:09:19 -0700368
369 return 0;
370}
371
372int
Koushik Duttab4c5fd62011-01-02 22:54:31 -0800373format_ext2_device (const char *device) {
374 // Run mke2fs
375 char *const mke2fs[] = {MKE2FS_BIN, device, NULL};
376 if(run_exec_process(mke2fs))
377 return -1;
378
379 // Run tune2fs
380 char *const tune2fs[] = {TUNE2FS_BIN, "-C", "1", device, NULL};
381 if(run_exec_process(tune2fs))
382 return -1;
383
384 // Run e2fsck
385 char *const e2fsck[] = {E2FSCK_BIN, "-fy", device, NULL};
386 if(run_exec_process(e2fsck))
387 return -1;
388
389 return 0;
390}
391
392int
393mmc_format_ext3 (MmcPartition *partition) {
394 char device[128];
395 strcpy(device, partition->device_index);
396 return format_ext3_device(device);
397}
398
399int
Shashank Mittal815ca5d2010-07-27 11:09:19 -0700400mmc_mount_partition(const MmcPartition *partition, const char *mount_point,
401 int read_only)
402{
403 const unsigned long flags = MS_NOATIME | MS_NODEV | MS_NODIRATIME;
404 char devname[128];
405 int rv = -1;
406 strcpy(devname, partition->device_index);
407 if (partition->filesystem == NULL) {
408 printf("Null filesystem!\n");
409 return rv;
410 }
411 if (!read_only) {
412 rv = mount(devname, mount_point, partition->filesystem, flags, NULL);
413 }
414 if (read_only || rv < 0) {
415 rv = mount(devname, mount_point, partition->filesystem, flags | MS_RDONLY, 0);
416 if (rv < 0) {
417 printf("Failed to mount %s on %s: %s\n",
418 devname, mount_point, strerror(errno));
419 } else {
420 printf("Mount %s on %s read-only\n", devname, mount_point);
421 }
422 }
423 return rv;
424}
425
426int
427mmc_raw_copy (const MmcPartition *partition, char *in_file) {
428 int ch;
429 FILE *in;
430 FILE *out;
431 int val = 0;
432 char buf[512];
433 unsigned sz = 0;
434 unsigned i;
435 int ret = -1;
436 char *out_file = partition->device_index;
437
438 in = fopen ( in_file, "r" );
439 if (in == NULL)
440 goto ERROR3;
441
442 out = fopen ( out_file, "w" );
443 if (out == NULL)
444 goto ERROR2;
445
446 fseek(in, 0L, SEEK_END);
447 sz = ftell(in);
448 fseek(in, 0L, SEEK_SET);
449
450 if (sz % 512)
451 {
452 while ( ( ch = fgetc ( in ) ) != EOF )
453 fputc ( ch, out );
454 }
455 else
456 {
457 for (i=0; i< (sz/512); i++)
458 {
459 if ((fread(buf, 512, 1, in)) != 1)
460 goto ERROR1;
461 if ((fwrite(buf, 512, 1, out)) != 1)
462 goto ERROR1;
463 }
464 }
465
466 fsync(out);
467 ret = 0;
468ERROR1:
469 fclose ( out );
470ERROR2:
471 fclose ( in );
472ERROR3:
473 return ret;
474
475}
476
Koushik Duttafef77c02010-11-09 20:03:42 -0800477
478int
Koushik Dutta59d86b42011-03-06 15:18:48 -0800479mmc_raw_dump_internal (const char* in_file, const char *out_file) {
Koushik Duttafef77c02010-11-09 20:03:42 -0800480 int ch;
481 FILE *in;
482 FILE *out;
483 int val = 0;
484 char buf[512];
485 unsigned sz = 0;
486 unsigned i;
487 int ret = -1;
Koushik Duttafef77c02010-11-09 20:03:42 -0800488
489 in = fopen ( in_file, "r" );
490 if (in == NULL)
491 goto ERROR3;
492
493 out = fopen ( out_file, "w" );
494 if (out == NULL)
495 goto ERROR2;
496
497 fseek(in, 0L, SEEK_END);
498 sz = ftell(in);
499 fseek(in, 0L, SEEK_SET);
500
501 if (sz % 512)
502 {
503 while ( ( ch = fgetc ( in ) ) != EOF )
504 fputc ( ch, out );
505 }
506 else
507 {
508 for (i=0; i< (sz/512); i++)
509 {
510 if ((fread(buf, 512, 1, in)) != 1)
511 goto ERROR1;
512 if ((fwrite(buf, 512, 1, out)) != 1)
513 goto ERROR1;
514 }
515 }
516
517 fsync(out);
518 ret = 0;
519ERROR1:
520 fclose ( out );
521ERROR2:
522 fclose ( in );
523ERROR3:
524 return ret;
525
526}
527
Koushik Dutta59d86b42011-03-06 15:18:48 -0800528// TODO: refactor this to not be a giant copy paste mess
529int
530mmc_raw_dump (const MmcPartition *partition, char *out_file) {
531 return mmc_raw_dump_internal(partition->device_index, out_file);
532}
533
Koushik Dutta19447c02010-11-10 10:40:44 -0800534
535int
536mmc_raw_read (const MmcPartition *partition, char *data, int data_size) {
537 int ch;
538 FILE *in;
539 int val = 0;
540 char buf[512];
541 unsigned sz = 0;
542 unsigned i;
543 int ret = -1;
544 char *in_file = partition->device_index;
545
546 in = fopen ( in_file, "r" );
547 if (in == NULL)
548 goto ERROR3;
549
550 fseek(in, 0L, SEEK_END);
551 sz = ftell(in);
552 fseek(in, 0L, SEEK_SET);
553
554 fread(data, data_size, 1, in);
555
556 ret = 0;
557ERROR1:
558ERROR2:
559 fclose ( in );
560ERROR3:
561 return ret;
562
563}
564
565int
566mmc_raw_write (const MmcPartition *partition, char *data, int data_size) {
567 int ch;
568 FILE *out;
569 int val = 0;
570 char buf[512];
571 unsigned sz = 0;
572 unsigned i;
573 int ret = -1;
574 char *out_file = partition->device_index;
575
576 out = fopen ( out_file, "w" );
577 if (out == NULL)
578 goto ERROR3;
579
580 fwrite(data, data_size, 1, out);
581
582 ret = 0;
583ERROR1:
584ERROR2:
585 fclose ( out );
586ERROR3:
587 return ret;
588
589}
590
Steve Kondik4123b582010-11-14 03:18:40 -0500591int cmd_mmc_restore_raw_partition(const char *partition, const char *filename)
Koushik Dutta19447c02010-11-10 10:40:44 -0800592{
Koushik Dutta67fa0c32011-03-17 11:37:21 -0700593 if (partition[0] != '/') {
594 mmc_scan_partitions();
595 const MmcPartition *p;
596 p = mmc_find_partition_by_name(partition);
597 if (p == NULL)
598 return -1;
599 return mmc_raw_copy(p, filename);
600 }
601 else {
602 return mmc_raw_dump_internal(filename, partition);
603 }
Koushik Dutta19447c02010-11-10 10:40:44 -0800604}
605
Steve Kondik4123b582010-11-14 03:18:40 -0500606int cmd_mmc_backup_raw_partition(const char *partition, const char *filename)
Koushik Dutta19447c02010-11-10 10:40:44 -0800607{
Koushik Dutta59d86b42011-03-06 15:18:48 -0800608 if (partition[0] != '/') {
Koushik Dutta67fa0c32011-03-17 11:37:21 -0700609 mmc_scan_partitions();
Koushik Dutta59d86b42011-03-06 15:18:48 -0800610 const MmcPartition *p;
611 p = mmc_find_partition_by_name(partition);
612 if (p == NULL)
613 return -1;
614 return mmc_raw_dump(p, filename);
615 }
616 else {
617 return mmc_raw_dump_internal(partition, filename);
618 }
Koushik Dutta19447c02010-11-10 10:40:44 -0800619}
620
Steve Kondik4123b582010-11-14 03:18:40 -0500621int cmd_mmc_erase_raw_partition(const char *partition)
Koushik Dutta19447c02010-11-10 10:40:44 -0800622{
Koushik Dutta19447c02010-11-10 10:40:44 -0800623 return 0;
624}
625
Steve Kondik4123b582010-11-14 03:18:40 -0500626int cmd_mmc_erase_partition(const char *partition, const char *filesystem)
Koushik Dutta19447c02010-11-10 10:40:44 -0800627{
628 mmc_scan_partitions();
629 const MmcPartition *p;
630 p = mmc_find_partition_by_name(partition);
631 if (p == NULL)
632 return -1;
633 return mmc_format_ext3 (p);
634}
635
Steve Kondik4123b582010-11-14 03:18:40 -0500636int cmd_mmc_mount_partition(const char *partition, const char *mount_point, const char *filesystem, int read_only)
Koushik Dutta19447c02010-11-10 10:40:44 -0800637{
638 mmc_scan_partitions();
639 const MmcPartition *p;
640 p = mmc_find_partition_by_name(partition);
641 if (p == NULL)
642 return -1;
643 return mmc_mount_partition(p, mount_point, read_only);
644}
645
Steve Kondik4123b582010-11-14 03:18:40 -0500646int cmd_mmc_get_partition_device(const char *partition, char *device)
Koushik Dutta19447c02010-11-10 10:40:44 -0800647{
648 mmc_scan_partitions();
649 const MmcPartition *p;
650 p = mmc_find_partition_by_name(partition);
651 if (p == NULL)
Koushik Dutta12154202010-11-11 01:16:14 -0800652 return -1;
653 strcpy(device, p->device_index);
654 return 0;
Koushik Dutta19447c02010-11-10 10:40:44 -0800655}