1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
|
http://www.2net.co.uk/tutorial/android-sparse-image-format
system/core/libsparse/backed_block.h
enum backed_block_type {
BACKED_BLOCK_DATA,
BACKED_BLOCK_FILE,
BACKED_BLOCK_FD,
BACKED_BLOCK_FILL,
};
struct backed_block {
unsigned int block;
unsigned int len;
enum backed_block_type type;
union {
struct {
void *data;
} data;
struct {
char *filename;
int64_t offset;
} file;
struct {
int fd;
int64_t offset;
} fd;
struct {
uint32_t val;
} fill;
};
struct backed_block *next;
};
system/core/libsparse/sparse_format.h
typedef struct sparse_header {
__le32 magic; /* 0xed26ff3a */
__le16 major_version; /* (0x1) - reject images with higher major versions */
__le16 minor_version; /* (0x0) - allow images with higer minor versions */
__le16 file_hdr_sz; /* 28 bytes for first revision of the file format */
__le16 chunk_hdr_sz; /* 12 bytes for first revision of the file format */
__le32 blk_sz; /* block size in bytes, must be a multiple of 4 (4096) */
__le32 total_blks; /* total blocks in the non-sparse output image */
__le32 total_chunks; /* total chunks in the sparse input image */
__le32 image_checksum; /* CRC32 checksum of the original data, counting "don't care" */
/* as 0. Standard 802.3 polynomial, use a Public Domain */
/* table implementation */
} sparse_header_t;
#define SPARSE_HEADER_MAGIC 0xed26ff3a
#define CHUNK_TYPE_RAW 0xCAC1
#define CHUNK_TYPE_FILL 0xCAC2
#define CHUNK_TYPE_DONT_CARE 0xCAC3
#define CHUNK_TYPE_CRC32 0xCAC4
typedef struct chunk_header {
__le16 chunk_type; /* 0xCAC1 -> raw; 0xCAC2 -> fill; 0xCAC3 -> don't care */
__le16 reserved1;
__le32 chunk_sz; /* in blocks in output image */
__le32 total_sz; /* in bytes of chunk input file including chunk header and data */
} chunk_header_t;
/* Following a Raw or Fill or CRC32 chunk is data.
* For a Raw chunk, it's the data in chunk_sz * blk_sz.
* For a Fill chunk, it's 4 bytes of the fill data.
* For a CRC32 chunk, it's 4 bytes of CRC32
*/
sparse_header_t sparse_header = {
.magic = SPARSE_HEADER_MAGIC,
.major_version = SPARSE_HEADER_MAJOR_VER,
.minor_version = SPARSE_HEADER_MINOR_VER,
.file_hdr_sz = SPARSE_HEADER_LEN,
.chunk_hdr_sz = CHUNK_HEADER_LEN,
.blk_sz = out->block_size,
.total_blks = out->len / out->block_size,
.total_chunks = chunks,
.image_checksum = 0
};
binary:
./out/host/linux-x86/bin/fastboot
./out/host/linux-x86/bin/simg2img
./out/host/linux-x86/bin/img2simg
./system/core/libsparse/simg_dump.py
files:
system/core/libsparse/output_file.c
./system/core/libsparse/simg_dump.py
system/core/libsparse/sparse.c
system/core/libsparse/backed_block.c
bb->type = BACKED_BLOCK_FILL <- backed_block_add_fill <- sparse_file_add_fill
system/core/libsparse/sparse_read.c
sparse_file_read->sparse_file_read_normal->sparse_file_add_fill
process_chunk->process_fill_chunk->sparse_file_add_fill
sparse_file_import_auto:
sparse_file_import
sparse_file_new
sparse_file_read_normal
system/core/libsparse/img2simg.c
main:
sparse_file_new
sparse_file_verbose
sparse_file_read in system/core/libsparse/sparse_read.c
sparse_file_write
sparse_count_chunks
output_file_open_fd
write_all_blocks
sparse_file_write_block
BACKED_BLOCK_DATA: write_data_chunk
BACKED_BLOCK_FILE: write_file_chunk
BACKED_BLOCK_FD: write_fd_chunk
BACKED_BLOCK_FILL: write_fill_chunk
system/core/libsparse/simg2img.c
main:
sparse_file_import
sparse_file_write
system/core/fastboot/fastboot.cpp:
main:
branch "flash" -- do_flash:
load_buf:
load_buf_fd:
get_sparse_limit
load_sparse_files
sparse_file_import_auto
sparse_file_import
sparse_file_new
sparse_file_read_normal
sparse_file_resparse
sparse_file_resparse
sparse_file_new
move_chunks_up_to_len
backed_block_list_move
buf->type = FB_BUFFER_SPARSE
buf->data = s
flash_buf:
sparse_file_len
fb_queue_flash_sparse
device/linaro/bootloader/OpenPlatformPkg/Platforms/Hisilicon/HiKey/HiKeyFastbootDxe/HiKeyFastboot.c
HiKeyFastbootPlatformFlashPartition
============== CHUNK_TYPE_DONT_CARE ================
system/core/libsparse/output_file.c
write_sparse_skip_chunk
<-- write_all_blocks in libsparse/sparse.c
system/core/libsparse/sparse_read.c
process_chunk
CHUNK_TYPE_FILL: process_fill_chunk
CHUNK_TYPE_DONT_CARE: process_skip_chunk
|