解压和生成 system.img&data.img ( yaffs2格式)

时间:2021-08-24 16:04:40

做为一名Android手机用户, 拿到system.img和data.img不是件难事

有这两个image可以做什么呢? ^_^可以做很多事,比如删除一些不想用的系统应用(/system/app目录下)


这里介绍的方法是针对image为yaffs2格式,也就是说android手机的存储设备是nand flash,  如果是emmc, 请看另一篇文章


(下面示例,适用于pagesize=2048 byte的nand  芯片)


1.  把system目录压缩成system.img

$out/host/linux-x86/bin/mkyaffs2image -f -c 2048 -s 64    out/target/product/{PRODUCT}/system  out/target/product/{PRODUCT}/system .img


mkyaffs2image由android源码工程编译而来,随便哪个android版本在external/yaffs2目录下都有它的源码,mm这个目录即可


2. 解压system.img

$unyaffs2 -p 2048 -s 64  system,img  system


源码如下,分别拷贝到Makefile,  unyaffs2.h, unyaffs2.c文件,再执行 make all编译即可生成unyaffs2可执行程序 

------------------------------------makefile-----------------------------------------------------------



CROSS =
CC    = $(CROSS)gcc
RM = rm -fr
CFLAGS =  -I.
CFLAGS += -O2
#CFLAGS += -Wall -Wshadow -Winline -Wpointer-arith -Wnested-externs \
#   -Wwrite-strings -Wstrict-prototypes -Wmissing-declarations \
#   -Wmissing-prototypes -Wredundant-decls


LDFLAGS += -lm


TARGET = unyaffs2
  
YAFF2SRCS = unyaffs2.c
YAFF2OBJS = $(YAFF2SRCS:.c=.o)


all: $(TARGET)

$(TARGET): $(YAFF2OBJS) 
$(CC) -o $@ $(YAFF2OBJS)  $(LDFLAGS)


distclean:
clean:
$(RM)  $(TARGET) $(YAFF2OBJS) 


.PHONY: all clean distclean $(TARGET)

-------------------------------------unyaffs2.h----------------------------------------------------------

/*
 * definition copied from yaffs2 project
 */


#ifndef __UNYAFFS_H__
#define __UNYAFFS_H__




#define YAFFS_MAX_NAME_LENGTH       255
#define YAFFS_MAX_ALIAS_LENGTH      159
/* Definition of types */
typedef unsigned char __u8;
typedef unsigned short __u16;
typedef unsigned __u32;


typedef struct {
    unsigned sequenceNumber;
    unsigned objectId;
    unsigned chunkId;
    unsigned byteCount;
} yaffs_PackedTags2TagsPart;


typedef struct {
    unsigned char colParity;
    unsigned lineParity;
    unsigned lineParityPrime; 
} yaffs_ECCOther;


typedef struct {
    yaffs_PackedTags2TagsPart t;
    yaffs_ECCOther ecc;
} yaffs_PackedTags2;


typedef enum {
    YAFFS_ECC_RESULT_UNKNOWN,
    YAFFS_ECC_RESULT_NO_ERROR,
    YAFFS_ECC_RESULT_FIXED,
    YAFFS_ECC_RESULT_UNFIXED
} yaffs_ECCResult;


typedef enum {
    YAFFS_OBJECT_TYPE_UNKNOWN,
    YAFFS_OBJECT_TYPE_FILE,
    YAFFS_OBJECT_TYPE_SYMLINK,
    YAFFS_OBJECT_TYPE_DIRECTORY,
    YAFFS_OBJECT_TYPE_HARDLINK,
    YAFFS_OBJECT_TYPE_SPECIAL
} yaffs_ObjectType;




typedef struct {


    unsigned validMarker0;
    unsigned chunkUsed; /*  Status of the chunk: used or unused */
    unsigned objectId;  /* If 0 then this is not part of an object (unused) */
    unsigned chunkId;   /* If 0 then this is a header, else a data chunk */
    unsigned byteCount; /* Only valid for data chunks */


    /* The following stuff only has meaning when we read */
    yaffs_ECCResult eccResult;
    unsigned blockBad;


    /* YAFFS 1 stuff */
    unsigned chunkDeleted;  /* The chunk is marked deleted */
    unsigned serialNumber;  /* Yaffs1 2-bit serial number */


    /* YAFFS2 stuff */
    unsigned sequenceNumber;    /* The sequence number of this block */


    /* Extra info if this is an object header (YAFFS2 only) */


    unsigned extraHeaderInfoAvailable;  /* There is extra info available if this is not zero */
    unsigned extraParentObjectId;   /* The parent object */
    unsigned extraIsShrinkHeader;   /* Is it a shrink header? */
    unsigned extraShadows;      /* Does this shadow another object? */


    yaffs_ObjectType extraObjectType;   /* What object type? */


    unsigned extraFileLength;       /* Length if it is a file */
    unsigned extraEquivalentObjectId;   /* Equivalent object Id if it is a hard link */


    unsigned validMarker1;


} yaffs_ExtendedTags;


/* -------------------------- Object structure -------------------------------*/
/* This is the object structure as stored on NAND */


typedef struct {
    yaffs_ObjectType type;


    /* Apply to everything  */
    int parentObjectId;
__u16 sum__NoLongerUsed;        /* checksum of name. No longer used */
char name[YAFFS_MAX_NAME_LENGTH + 1];


/* The following apply to directories, files, symlinks - not hard links */
__u32 yst_mode;         /* protection */


#ifdef CONFIG_YAFFS_WINCE
    __u32 notForWinCE[5];
#else
    __u32 yst_uid;
    __u32 yst_gid;
    __u32 yst_atime;
    __u32 yst_mtime;
    __u32 yst_ctime;
#endif


    /* File size  applies to files only */
    int fileSize;


    /* Equivalent object id applies to hard links only. */
    int equivalentObjectId;


    /* Alias is for symlinks only. */
    char alias[YAFFS_MAX_ALIAS_LENGTH + 1];


    __u32 yst_rdev;     /* device stuff for block and char devices (major/min) */


#ifdef CONFIG_YAFFS_WINCE
    __u32 win_ctime[2];
    __u32 win_atime[2];
    __u32 win_mtime[2];
#else
    __u32 roomToGrow[6];


#endif
    __u32 inbandShadowsObject;
    __u32 inbandIsShrink;


    __u32 reservedSpace[2];
    int shadowsObject;  /* This object header shadows the specified object if > 0 */


    /* isShrink applies to object headers written when we shrink the file (ie resize) */
    __u32 isShrink;


} yaffs_ObjectHeader;


#endif

-------------------------------------unyaffs2.c----------------------------------------------------------

#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <limits.h>
#include <getopt.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <sys/param.h>
#include <sys/types.h>




#ifdef _HAVE_LUTIMES
#include <sys/time.h>
#else
#include <utime.h>
#endif


#include "unyaffs2.h"


#define UNYAFFS_PRINTF(s, args...) \
do { \
fprintf(stdout, s, ##args); \
fflush(stdout); \
} while (0)




#define VENDOR_EDIT


#define MAX_OBJECTS 10000
#define YAFFS_OBJECTID_ROOT     1
#define MAX_PAGE_SIZE 16384
#define MAX_SPARE_SIZE 512


unsigned int page_size=2048;
unsigned int spare_size=64;
unsigned char data[MAX_PAGE_SIZE + MAX_SPARE_SIZE];
unsigned char *chunk_data = NULL;
unsigned char *spare_data = NULL;
int img_file = 0;
char *obj_list[MAX_OBJECTS];


#ifdef VENDOR_EDIT
//set file attrib include access time & owner & mode, scott 2012
static int unyaffs2_obj_chattr (const char *fpath,  yaffs_ObjectHeader *obj)
{
/* access time */
#ifdef _HAVE_LUTIMES
struct timeval ftime[2];


ftime[0].tv_sec = obj->yst_atime;
ftime[0].tv_usec = 0;
ftime[1].tv_sec = obj->yst_mtime;
ftime[1].tv_usec = 0;


lutimes(fpath, ftime);
#else
struct utimbuf ftime;


ftime.actime = obj->yst_atime;
ftime.modtime = obj->yst_mtime;


utime(fpath, &ftime);
#endif


/* owner */
lchown(fpath, obj->yst_uid, obj->yst_gid);


/* mode - no effect on symbolic link */
if (obj->type != YAFFS_OBJECT_TYPE_SYMLINK)
chmod(fpath, obj->yst_mode);

return 0;
}


#endif


int read_chunk()
{
ssize_t s;
int ret = -1;
memset(chunk_data, 0xff, sizeof(chunk_data));
s = read(img_file, data, page_size + spare_size);
if (s == -1) {
perror("read image file\n");
} else if (s == 0) {
printf("end of image\n");
} else if ((s == (page_size + spare_size))) {
ret = 0;
} else {
fprintf(stderr, "broken image file\n");
}
return ret;
}


int process_chunk()
{
int out_file, remain, s;
char *full_path_name;


yaffs_PackedTags2 *pt = (yaffs_PackedTags2 *)spare_data;
if (pt->t.byteCount == 0xffff)  {//a new object 


yaffs_ObjectHeader *oh = (yaffs_ObjectHeader *)malloc(sizeof(yaffs_ObjectHeader));
memcpy(oh, chunk_data, sizeof(yaffs_ObjectHeader));


full_path_name = (char *)malloc(strlen(oh->name) + strlen(obj_list[oh->parentObjectId]) + 2);
if (full_path_name == NULL) {
perror("malloc full path name\n");
}
strcpy(full_path_name, obj_list[oh->parentObjectId]);
strcat(full_path_name, "/");
strcat(full_path_name, oh->name);
obj_list[pt->t.objectId] = full_path_name;


switch(oh->type) {
case YAFFS_OBJECT_TYPE_FILE:
remain = oh->fileSize;
out_file = creat(full_path_name, oh->yst_mode);
while(remain > 0) {
if (read_chunk())
return -1;
s = (remain < pt->t.byteCount) ? remain : pt->t.byteCount;
if (write(out_file, chunk_data, s) == -1)
return -1;
remain -= s;
}
close(out_file);
#ifdef VENDOR_EDIT
unyaffs2_obj_chattr(full_path_name,oh);
#endif
break;
case YAFFS_OBJECT_TYPE_SYMLINK:
symlink(oh->alias, full_path_name);
#ifdef VENDOR_EDIT
unyaffs2_obj_chattr(full_path_name,oh);
#endif
break;
case YAFFS_OBJECT_TYPE_DIRECTORY:
mkdir(full_path_name, 0777);
#ifdef VENDOR_EDIT
unyaffs2_obj_chattr(full_path_name,oh);
#endif
break;
case YAFFS_OBJECT_TYPE_HARDLINK:
link(obj_list[oh->equivalentObjectId], full_path_name);
break;
}
}
return 0;
}




static int helper (void)
{
UNYAFFS_PRINTF("unyaffs2 - A utility to extract the yaffs2 image\n\n");
UNYAFFS_PRINTF("Usage: unyaffs2 [-h|--help] \n"
        "                [-p|--pagesize pagesize] [-s|--sparesize sparesize]\n"
          "                imgfile dirname\n\n");
UNYAFFS_PRINTF("Options :\n");
UNYAFFS_PRINTF("  -h                 display this help message and exit.\n");
UNYAFFS_PRINTF("  -p pagesize        page size of target device.\n"
          "                     (512|2048(default)|4096|(8192|16384) bytes)\n");
UNYAFFS_PRINTF("  -s sparesize       spare size of target device.\n"
          "                     (default: pagesize/64 bytes; max: pagesize)\n");


return -1;
}


int main(int argc, char **argv)
{
char *imagefile= NULL;
char *dirpath = NULL;
int option, option_index;
static const char *short_options = "hp:s:";
static const struct option long_options[] = {
{"pagesize", required_argument, 0, 'p'},
{"sparesize", required_argument, 0, 's'},
{"help", no_argument, 0, 'h'},
{NULL, no_argument, 0, '\0'},
};


page_size = 2048;
spare_size= 64;


while ((option = getopt_long(argc, argv, short_options,
    long_options, &option_index)) != EOF) 
{
switch (option) {
case 'p':
page_size = strtol(optarg, NULL, 10);
break;
case 's':
spare_size = strtol(optarg, NULL, 10);
break;
case 'h':
default:
return helper();
}
}


if (argc - optind < 2)
return helper();


imagefile = argv[optind];
dirpath   = argv[optind + 1];


chunk_data = data;
    spare_data = data + page_size;


img_file = open(imagefile, O_RDONLY);
if (img_file == -1) {
printf("open image file failed\n");
exit(1);
}


obj_list[YAFFS_OBJECTID_ROOT] = dirpath;//".";

while(1) {
if (read_chunk() == -1)
break;
process_chunk();
}
close(img_file);
return 0;
}