[recovery]: Add support for OTA upgrade on mmc devices.
Change-Id: I8f230dfa5be4e9f142765797d949e10434e1fdeb
This commit is contained in:
parent
0209a62c7d
commit
815ca5d230
@ -149,7 +149,7 @@ else
|
||||
endif
|
||||
LOCAL_STATIC_LIBRARIES += libbusybox libclearsilverregex libmkyaffs2image libunyaffs liberase_image libdump_image libflash_image libmtdutils
|
||||
LOCAL_STATIC_LIBRARIES += libamend
|
||||
LOCAL_STATIC_LIBRARIES += libminzip libunz libmtdutils libmincrypt
|
||||
LOCAL_STATIC_LIBRARIES += libminzip libunz libmtdutils libmmcutils libmincrypt
|
||||
LOCAL_STATIC_LIBRARIES += libminui libpixelflinger_static libpng libcutils
|
||||
LOCAL_STATIC_LIBRARIES += libstdc++ libc
|
||||
|
||||
@ -216,6 +216,7 @@ include $(commands_recovery_local_path)/bmlutils/Android.mk
|
||||
include $(commands_recovery_local_path)/minui/Android.mk
|
||||
include $(commands_recovery_local_path)/minzip/Android.mk
|
||||
include $(commands_recovery_local_path)/mtdutils/Android.mk
|
||||
include $(commands_recovery_local_path)/mmcutils/Android.mk
|
||||
include $(commands_recovery_local_path)/tools/Android.mk
|
||||
include $(commands_recovery_local_path)/edify/Android.mk
|
||||
include $(commands_recovery_local_path)/updater/Android.mk
|
||||
|
15
mmcutils/Android.mk
Normal file
15
mmcutils/Android.mk
Normal file
@ -0,0 +1,15 @@
|
||||
ifneq ($(TARGET_SIMULATOR),true)
|
||||
ifeq ($(TARGET_ARCH),arm)
|
||||
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_SRC_FILES := \
|
||||
mmcutils.c
|
||||
|
||||
LOCAL_MODULE := libmmcutils
|
||||
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
|
||||
endif # TARGET_ARCH == arm
|
||||
endif # !TARGET_SIMULATOR
|
415
mmcutils/mmcutils.c
Normal file
415
mmcutils/mmcutils.c
Normal file
@ -0,0 +1,415 @@
|
||||
/*
|
||||
* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials provided
|
||||
* with the distribution.
|
||||
* * Neither the name of Code Aurora Forum, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
||||
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <dirent.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/reboot.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/mount.h> // for _IOW, _IOR, mount()
|
||||
|
||||
#include "mmcutils.h"
|
||||
|
||||
unsigned ext3_count = 0;
|
||||
char *ext3_partitions[] = {"system", "userdata", "cache", "NONE"};
|
||||
|
||||
unsigned vfat_count = 0;
|
||||
char *vfat_partitions[] = {"modem", "NONE"};
|
||||
|
||||
struct MmcPartition {
|
||||
char *device_index;
|
||||
char *filesystem;
|
||||
char *name;
|
||||
unsigned dstatus;
|
||||
unsigned dtype ;
|
||||
unsigned dfirstsec;
|
||||
unsigned dsize;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
MmcPartition *partitions;
|
||||
int partitions_allocd;
|
||||
int partition_count;
|
||||
} MmcState;
|
||||
|
||||
static MmcState g_mmc_state = {
|
||||
NULL, // partitions
|
||||
0, // partitions_allocd
|
||||
-1 // partition_count
|
||||
};
|
||||
|
||||
#define MMC_DEVICENAME "/dev/block/mmcblk0"
|
||||
|
||||
static void
|
||||
mmc_partition_name (MmcPartition *mbr, unsigned int type) {
|
||||
switch(type)
|
||||
{
|
||||
char name[64];
|
||||
case MMC_BOOT_TYPE:
|
||||
sprintf(name,"boot");
|
||||
mbr->name = strdup(name);
|
||||
break;
|
||||
case MMC_EXT3_TYPE:
|
||||
if (strcmp("NONE", ext3_partitions[ext3_count])) {
|
||||
strcpy((char *)name,(const char *)ext3_partitions[ext3_count]);
|
||||
mbr->name = strdup(name);
|
||||
ext3_count++;
|
||||
}
|
||||
mbr->filesystem = strdup("ext3");
|
||||
break;
|
||||
case MMC_VFAT_TYPE:
|
||||
if (strcmp("NONE", vfat_partitions[vfat_count])) {
|
||||
strcpy((char *)name,(const char *)vfat_partitions[vfat_count]);
|
||||
mbr->name = strdup(name);
|
||||
vfat_count++;
|
||||
}
|
||||
mbr->filesystem = strdup("vfat");
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
static int
|
||||
mmc_read_mbr (const char *device, MmcPartition *mbr) {
|
||||
FILE *fd;
|
||||
unsigned char buffer[512];
|
||||
int idx, i;
|
||||
unsigned mmc_partition_count = 0;
|
||||
unsigned int dtype;
|
||||
unsigned int dfirstsec;
|
||||
unsigned int EBR_first_sec;
|
||||
unsigned int EBR_current_sec;
|
||||
int ret = -1;
|
||||
|
||||
fd = fopen(device, "r");
|
||||
if(fd == NULL)
|
||||
{
|
||||
printf("Can't open device: \"%s\"\n", device);
|
||||
goto ERROR2;
|
||||
}
|
||||
if ((fread(buffer, 512, 1, fd)) != 1)
|
||||
{
|
||||
printf("Can't read device: \"%s\"\n", device);
|
||||
goto ERROR1;
|
||||
}
|
||||
/* Check to see if signature exists */
|
||||
if ((buffer[TABLE_SIGNATURE] != 0x55) || \
|
||||
(buffer[TABLE_SIGNATURE + 1] != 0xAA))
|
||||
{
|
||||
printf("Incorrect mbr signatures!\n");
|
||||
goto ERROR1;
|
||||
}
|
||||
idx = TABLE_ENTRY_0;
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
char device_index[128];
|
||||
|
||||
mbr[mmc_partition_count].dstatus = \
|
||||
buffer[idx + i * TABLE_ENTRY_SIZE + OFFSET_STATUS];
|
||||
mbr[mmc_partition_count].dtype = \
|
||||
buffer[idx + i * TABLE_ENTRY_SIZE + OFFSET_TYPE];
|
||||
mbr[mmc_partition_count].dfirstsec = \
|
||||
GET_LWORD_FROM_BYTE(&buffer[idx + \
|
||||
i * TABLE_ENTRY_SIZE + \
|
||||
OFFSET_FIRST_SEC]);
|
||||
mbr[mmc_partition_count].dsize = \
|
||||
GET_LWORD_FROM_BYTE(&buffer[idx + \
|
||||
i * TABLE_ENTRY_SIZE + \
|
||||
OFFSET_SIZE]);
|
||||
dtype = mbr[mmc_partition_count].dtype;
|
||||
dfirstsec = mbr[mmc_partition_count].dfirstsec;
|
||||
mmc_partition_name(&mbr[mmc_partition_count], \
|
||||
mbr[mmc_partition_count].dtype);
|
||||
|
||||
sprintf(device_index, "%sp%d", device, (mmc_partition_count+1));
|
||||
mbr[mmc_partition_count].device_index = strdup(device_index);
|
||||
|
||||
mmc_partition_count++;
|
||||
if (mmc_partition_count == MAX_PARTITIONS)
|
||||
goto SUCCESS;
|
||||
}
|
||||
|
||||
/* See if the last partition is EBR, if not, parsing is done */
|
||||
if (dtype != 0x05)
|
||||
{
|
||||
goto SUCCESS;
|
||||
}
|
||||
|
||||
EBR_first_sec = dfirstsec;
|
||||
EBR_current_sec = dfirstsec;
|
||||
|
||||
fseek (fd, (EBR_first_sec * 512), SEEK_SET);
|
||||
if ((fread(buffer, 512, 1, fd)) != 1)
|
||||
goto ERROR1;
|
||||
|
||||
/* Loop to parse the EBR */
|
||||
for (i = 0;; i++)
|
||||
{
|
||||
char device_index[128];
|
||||
|
||||
if ((buffer[TABLE_SIGNATURE] != 0x55) || (buffer[TABLE_SIGNATURE + 1] != 0xAA))
|
||||
{
|
||||
break;
|
||||
}
|
||||
mbr[mmc_partition_count].dstatus = \
|
||||
buffer[TABLE_ENTRY_0 + OFFSET_STATUS];
|
||||
mbr[mmc_partition_count].dtype = \
|
||||
buffer[TABLE_ENTRY_0 + OFFSET_TYPE];
|
||||
mbr[mmc_partition_count].dfirstsec = \
|
||||
GET_LWORD_FROM_BYTE(&buffer[TABLE_ENTRY_0 + \
|
||||
OFFSET_FIRST_SEC]) + \
|
||||
EBR_current_sec;
|
||||
mbr[mmc_partition_count].dsize = \
|
||||
GET_LWORD_FROM_BYTE(&buffer[TABLE_ENTRY_0 + \
|
||||
OFFSET_SIZE]);
|
||||
mmc_partition_name(&mbr[mmc_partition_count], \
|
||||
mbr[mmc_partition_count].dtype);
|
||||
|
||||
sprintf(device_index, "%sp%d", device, (mmc_partition_count+1));
|
||||
mbr[mmc_partition_count].device_index = strdup(device_index);
|
||||
|
||||
mmc_partition_count++;
|
||||
if (mmc_partition_count == MAX_PARTITIONS)
|
||||
goto SUCCESS;
|
||||
|
||||
dfirstsec = GET_LWORD_FROM_BYTE(&buffer[TABLE_ENTRY_1 + OFFSET_FIRST_SEC]);
|
||||
if(dfirstsec == 0)
|
||||
{
|
||||
/* Getting to the end of the EBR tables */
|
||||
break;
|
||||
}
|
||||
/* More EBR to follow - read in the next EBR sector */
|
||||
fseek (fd, ((EBR_first_sec + dfirstsec) * 512), SEEK_SET);
|
||||
if ((fread(buffer, 512, 1, fd)) != 1)
|
||||
goto ERROR1;
|
||||
|
||||
EBR_current_sec = EBR_first_sec + dfirstsec;
|
||||
}
|
||||
|
||||
SUCCESS:
|
||||
ret = mmc_partition_count;
|
||||
ERROR1:
|
||||
fclose(fd);
|
||||
ERROR2:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
mmc_scan_partitions() {
|
||||
int i;
|
||||
ssize_t nbytes;
|
||||
|
||||
if (g_mmc_state.partitions == NULL) {
|
||||
const int nump = MAX_PARTITIONS;
|
||||
MmcPartition *partitions = malloc(nump * sizeof(*partitions));
|
||||
if (partitions == NULL) {
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
g_mmc_state.partitions = partitions;
|
||||
g_mmc_state.partitions_allocd = nump;
|
||||
memset(partitions, 0, nump * sizeof(*partitions));
|
||||
}
|
||||
g_mmc_state.partition_count = 0;
|
||||
ext3_count = 0;
|
||||
vfat_count = 0;
|
||||
|
||||
/* Initialize all of the entries to make things easier later.
|
||||
* (Lets us handle sparsely-numbered partitions, which
|
||||
* may not even be possible.)
|
||||
*/
|
||||
for (i = 0; i < g_mmc_state.partitions_allocd; i++) {
|
||||
MmcPartition *p = &g_mmc_state.partitions[i];
|
||||
if (p->device_index != NULL) {
|
||||
free(p->device_index);
|
||||
p->device_index = NULL;
|
||||
}
|
||||
if (p->name != NULL) {
|
||||
free(p->name);
|
||||
p->name = NULL;
|
||||
}
|
||||
if (p->filesystem != NULL) {
|
||||
free(p->filesystem);
|
||||
p->filesystem = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
g_mmc_state.partition_count = mmc_read_mbr(MMC_DEVICENAME, g_mmc_state.partitions);
|
||||
if(g_mmc_state.partition_count == -1)
|
||||
{
|
||||
printf("Error in reading mbr!\n");
|
||||
// keep "partitions" around so we can free the names on a rescan.
|
||||
g_mmc_state.partition_count = -1;
|
||||
}
|
||||
return g_mmc_state.partition_count;
|
||||
}
|
||||
|
||||
const MmcPartition *
|
||||
mmc_find_partition_by_name(const char *name)
|
||||
{
|
||||
if (g_mmc_state.partitions != NULL) {
|
||||
int i;
|
||||
for (i = 0; i < g_mmc_state.partitions_allocd; i++) {
|
||||
MmcPartition *p = &g_mmc_state.partitions[i];
|
||||
if (p->device_index !=NULL && p->name != NULL) {
|
||||
if (strcmp(p->name, name) == 0) {
|
||||
return p;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#define MKE2FS_BIN "/sbin/mke2fs_static"
|
||||
#define TUNE2FS_BIN "/sbin/tune2fs_static"
|
||||
#define E2FSCK_BIN "/sbin/e2fsck_static"
|
||||
|
||||
static int
|
||||
run_exec_process ( char **argv) {
|
||||
pid_t pid;
|
||||
int status;
|
||||
pid = fork();
|
||||
if (pid == 0) {
|
||||
execv(argv[0], argv);
|
||||
fprintf(stderr, "E:Can't run (%s)\n",strerror(errno));
|
||||
_exit(-1);
|
||||
}
|
||||
|
||||
waitpid(pid, &status, 0);
|
||||
if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
mmc_format_ext3 (MmcPartition *partition) {
|
||||
char device[128];
|
||||
strcpy(device, partition->device_index);
|
||||
// Run mke2fs
|
||||
char *const mke2fs[] = {MKE2FS_BIN, "-j", device, NULL};
|
||||
if(run_exec_process(mke2fs))
|
||||
return -1;
|
||||
|
||||
// Run tune2fs
|
||||
char *const tune2fs[] = {TUNE2FS_BIN, "-C", "1", device, NULL};
|
||||
if(run_exec_process(tune2fs))
|
||||
return -1;
|
||||
|
||||
// Run e2fsck
|
||||
char *const e2fsck[] = {E2FSCK_BIN, "-fy", device, NULL};
|
||||
if(run_exec_process(e2fsck))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
mmc_mount_partition(const MmcPartition *partition, const char *mount_point,
|
||||
int read_only)
|
||||
{
|
||||
const unsigned long flags = MS_NOATIME | MS_NODEV | MS_NODIRATIME;
|
||||
char devname[128];
|
||||
int rv = -1;
|
||||
strcpy(devname, partition->device_index);
|
||||
if (partition->filesystem == NULL) {
|
||||
printf("Null filesystem!\n");
|
||||
return rv;
|
||||
}
|
||||
if (!read_only) {
|
||||
rv = mount(devname, mount_point, partition->filesystem, flags, NULL);
|
||||
}
|
||||
if (read_only || rv < 0) {
|
||||
rv = mount(devname, mount_point, partition->filesystem, flags | MS_RDONLY, 0);
|
||||
if (rv < 0) {
|
||||
printf("Failed to mount %s on %s: %s\n",
|
||||
devname, mount_point, strerror(errno));
|
||||
} else {
|
||||
printf("Mount %s on %s read-only\n", devname, mount_point);
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
int
|
||||
mmc_raw_copy (const MmcPartition *partition, char *in_file) {
|
||||
int ch;
|
||||
FILE *in;
|
||||
FILE *out;
|
||||
int val = 0;
|
||||
char buf[512];
|
||||
unsigned sz = 0;
|
||||
unsigned i;
|
||||
int ret = -1;
|
||||
char *out_file = partition->device_index;
|
||||
|
||||
in = fopen ( in_file, "r" );
|
||||
if (in == NULL)
|
||||
goto ERROR3;
|
||||
|
||||
out = fopen ( out_file, "w" );
|
||||
if (out == NULL)
|
||||
goto ERROR2;
|
||||
|
||||
fseek(in, 0L, SEEK_END);
|
||||
sz = ftell(in);
|
||||
fseek(in, 0L, SEEK_SET);
|
||||
|
||||
if (sz % 512)
|
||||
{
|
||||
while ( ( ch = fgetc ( in ) ) != EOF )
|
||||
fputc ( ch, out );
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i=0; i< (sz/512); i++)
|
||||
{
|
||||
if ((fread(buf, 512, 1, in)) != 1)
|
||||
goto ERROR1;
|
||||
if ((fwrite(buf, 512, 1, out)) != 1)
|
||||
goto ERROR1;
|
||||
}
|
||||
}
|
||||
|
||||
fsync(out);
|
||||
ret = 0;
|
||||
ERROR1:
|
||||
fclose ( out );
|
||||
ERROR2:
|
||||
fclose ( in );
|
||||
ERROR3:
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
85
mmcutils/mmcutils.h
Normal file
85
mmcutils/mmcutils.h
Normal file
@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials provided
|
||||
* with the distribution.
|
||||
* * Neither the name of Code Aurora Forum, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
||||
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef MMCUTILS_H_
|
||||
#define MMCUTILS_H_
|
||||
|
||||
/* Some useful define used to access the MBR/EBR table */
|
||||
#define BLOCK_SIZE 0x200
|
||||
#define TABLE_ENTRY_0 0x1BE
|
||||
#define TABLE_ENTRY_1 0x1CE
|
||||
#define TABLE_ENTRY_2 0x1DE
|
||||
#define TABLE_ENTRY_3 0x1EE
|
||||
#define TABLE_SIGNATURE 0x1FE
|
||||
#define TABLE_ENTRY_SIZE 0x010
|
||||
|
||||
#define OFFSET_STATUS 0x00
|
||||
#define OFFSET_TYPE 0x04
|
||||
#define OFFSET_FIRST_SEC 0x08
|
||||
#define OFFSET_SIZE 0x0C
|
||||
#define COPYBUFF_SIZE (1024 * 16)
|
||||
#define BINARY_IN_TABLE_SIZE (16 * 512)
|
||||
#define MAX_FILE_ENTRIES 20
|
||||
|
||||
#define MMC_BOOT_TYPE 0x48
|
||||
#define MMC_SYSTEM_TYPE 0x82
|
||||
#define MMC_USERDATA_TYPE 0x83
|
||||
|
||||
#define MMC_RCA 2
|
||||
|
||||
#define MAX_PARTITIONS 64
|
||||
|
||||
#define GET_LWORD_FROM_BYTE(x) ((unsigned)*(x) | \
|
||||
((unsigned)*((x)+1) << 8) | \
|
||||
((unsigned)*((x)+2) << 16) | \
|
||||
((unsigned)*((x)+3) << 24))
|
||||
|
||||
#define PUT_LWORD_TO_BYTE(x, y) do{*(x) = (y) & 0xff; \
|
||||
*((x)+1) = ((y) >> 8) & 0xff; \
|
||||
*((x)+2) = ((y) >> 16) & 0xff; \
|
||||
*((x)+3) = ((y) >> 24) & 0xff; }while(0)
|
||||
|
||||
#define GET_PAR_NUM_FROM_POS(x) ((((x) & 0x0000FF00) >> 8) + ((x) & 0x000000FF))
|
||||
|
||||
#define MMC_BOOT_TYPE 0x48
|
||||
#define MMC_EXT3_TYPE 0x83
|
||||
#define MMC_VFAT_TYPE 0xC
|
||||
typedef struct MmcPartition MmcPartition;
|
||||
|
||||
/* Functions */
|
||||
int mmc_scan_partitions();
|
||||
const MmcPartition *mmc_find_partition_by_name(const char *name);
|
||||
int mmc_format_ext3 (MmcPartition *partition);
|
||||
int mmc_mount_partition(const MmcPartition *partition, const char *mount_point, \
|
||||
int read_only);
|
||||
int mmc_raw_copy (const MmcPartition *partition, char *in_file);
|
||||
|
||||
#endif // MMCUTILS_H_
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -573,6 +574,7 @@ main(int argc, char **argv) {
|
||||
|
||||
ui_init();
|
||||
ui_print(EXPAND(RECOVERY_VERSION)"\n");
|
||||
set_root_table();
|
||||
get_args(&argc, &argv);
|
||||
|
||||
int previous_runs = 0;
|
||||
|
21
roots.c
21
roots.c
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -25,6 +26,7 @@
|
||||
|
||||
#include "mtdutils/mtdutils.h"
|
||||
#include "mtdutils/mounts.h"
|
||||
#include "mmcutils/mmcutils.h"
|
||||
#include "minzip/Zip.h"
|
||||
#include "roots.h"
|
||||
#include "common.h"
|
||||
@ -35,6 +37,7 @@
|
||||
xxx may just want to use enums
|
||||
*/
|
||||
static const char g_mtd_device[] = "@\0g_mtd_device";
|
||||
static const char g_mmc_device[] = "@\0g_mmc_device";
|
||||
static const char g_raw[] = "@\0g_raw";
|
||||
static const char g_package_file[] = "@\0g_package_file";
|
||||
|
||||
@ -383,6 +386,22 @@ format_root_device(const char *root)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//Handle MMC device types
|
||||
if(info->device == g_mmc_device) {
|
||||
mmc_scan_partitions();
|
||||
const MmcPartition *partition;
|
||||
partition = mmc_find_partition_by_name(info->partition_name);
|
||||
if (partition == NULL) {
|
||||
LOGE("format_root_device: can't find mmc partition \"%s\"\n",
|
||||
info->partition_name);
|
||||
return -1;
|
||||
}
|
||||
if (!strcmp(info->filesystem, "ext3")) {
|
||||
if(mmc_format_ext3(partition))
|
||||
LOGE("\n\"%s\" wipe failed!\n", info->partition_name);
|
||||
}
|
||||
}
|
||||
|
||||
return format_non_mtd_device(root);
|
||||
}
|
||||
|
1
roots.h
1
roots.h
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -24,7 +24,7 @@ ifdef BOARD_USES_BMLUTILS
|
||||
endif
|
||||
|
||||
LOCAL_STATIC_LIBRARIES += $(TARGET_RECOVERY_UPDATER_LIBS) $(TARGET_RECOVERY_UPDATER_EXTRA_LIBS)
|
||||
LOCAL_STATIC_LIBRARIES += libapplypatch libedify libmtdutils libminzip libz
|
||||
LOCAL_STATIC_LIBRARIES += libapplypatch libedify libmtdutils libmmcutils libminzip libz
|
||||
LOCAL_STATIC_LIBRARIES += libmincrypt libbz
|
||||
LOCAL_STATIC_LIBRARIES += libcutils libstdc++ libc
|
||||
LOCAL_C_INCLUDES += $(LOCAL_PATH)/..
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2009 The Android Open Source Project
|
||||
* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -33,6 +34,7 @@
|
||||
#include "minzip/DirUtil.h"
|
||||
#include "mtdutils/mounts.h"
|
||||
#include "mtdutils/mtdutils.h"
|
||||
#include "mmcutils/mmcutils.h"
|
||||
#include "updater.h"
|
||||
#include "applypatch/applypatch.h"
|
||||
|
||||
@ -84,6 +86,23 @@ Value* MountFn(const char* name, State* state, int argc, Expr* argv[]) {
|
||||
goto done;
|
||||
}
|
||||
result = mount_point;
|
||||
} else if (strcmp(type, "MMC") == 0) {
|
||||
mmc_scan_partitions();
|
||||
const MmcPartition* mmc;
|
||||
mmc = mmc_find_partition_by_name(location);
|
||||
if (mmc == NULL) {
|
||||
fprintf(stderr, "%s: no mmc partition named \"%s\"",
|
||||
name, location);
|
||||
result = strdup("");
|
||||
goto done;
|
||||
}
|
||||
if (mmc_mount_partition(mmc, mount_point, 0 /* rw */) != 0) {
|
||||
fprintf(stderr, "mmc mount of %s failed: %s\n",
|
||||
location, strerror(errno));
|
||||
result = strdup("");
|
||||
goto done;
|
||||
}
|
||||
result = mount_point;
|
||||
} else {
|
||||
if (mount(location, mount_point, type,
|
||||
MS_NOATIME | MS_NODEV | MS_NODIRATIME, "") < 0) {
|
||||
@ -211,11 +230,24 @@ Value* FormatFn(const char* name, State* state, int argc, Expr* argv[]) {
|
||||
result = strdup("");
|
||||
goto done;
|
||||
}
|
||||
result = location;
|
||||
} else if (strcmp(type, "MMC") == 0) {
|
||||
mmc_scan_partitions();
|
||||
const MmcPartition* mmc = mmc_find_partition_by_name(location);
|
||||
if (mmc == NULL) {
|
||||
fprintf(stderr, "%s: no mmc partition named \"%s\"",
|
||||
name, location);
|
||||
result = strdup("");
|
||||
goto done;
|
||||
}
|
||||
if (mmc_format_ext3(mmc))
|
||||
{
|
||||
result = strdup("");
|
||||
goto done;
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "%s: unsupported type \"%s\"", name, type);
|
||||
}
|
||||
|
||||
result = location;
|
||||
done:
|
||||
free(type);
|
||||
if (result != location) free(location);
|
||||
@ -660,7 +692,7 @@ Value* WriteRawImageFn(const char* name, State* state, int argc, Expr* argv[]) {
|
||||
if (mtd == NULL) {
|
||||
fprintf(stderr, "%s: no mtd partition named \"%s\"\n", name, partition);
|
||||
result = strdup("");
|
||||
goto done;
|
||||
goto MMC;
|
||||
}
|
||||
|
||||
MtdWriteContext* ctx = mtd_write_partition(mtd);
|
||||
@ -706,6 +738,22 @@ Value* WriteRawImageFn(const char* name, State* state, int argc, Expr* argv[]) {
|
||||
success ? "wrote" : "failed to write", partition, filename);
|
||||
|
||||
result = success ? partition : strdup("");
|
||||
goto done;
|
||||
|
||||
MMC:
|
||||
mmc_scan_partitions();
|
||||
const MmcPartition* mmc = mmc_find_partition_by_name(partition);
|
||||
if (mmc == NULL) {
|
||||
fprintf(stderr, "%s: no mmc partition named \"%s\"\n", name, partition);
|
||||
result = strdup("");
|
||||
goto done;
|
||||
}
|
||||
if (mmc_raw_copy(mmc, filename)) {
|
||||
fprintf(stderr, "%s: error erasing mmc partition named \"%s\"\n", name, partition);
|
||||
result = strdup("");
|
||||
goto done;
|
||||
}
|
||||
result = partition;
|
||||
#endif
|
||||
|
||||
done:
|
||||
|
Loading…
Reference in New Issue
Block a user