Rizin
unix-like reverse engineering framework and cli tools
bin_bootimg.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2015-2019 pancake <pancake@nopcode.org>
2 // SPDX-License-Identifier: LGPL-3.0-only
3 
4 #include <rz_types.h>
5 #include <rz_util.h>
6 #include <rz_lib.h>
7 #include <rz_bin.h>
8 
9 typedef struct boot_img_hdr BootImage;
10 
11 #define BOOT_MAGIC "ANDROID!"
12 #define BOOT_MAGIC_SIZE 8
13 #define BOOT_NAME_SIZE 16
14 #define BOOT_ARGS_SIZE 512
15 #define BOOT_EXTRA_ARGS_SIZE 1024
16 
17 #define ADD_REMAINDER(val, aln) ((val) + ((aln) != 0 ? ((val) % (aln)) : 0))
18 #define ROUND_DOWN(val, aln) ((aln) != 0 ? (((val) / (aln)) * (aln)) : (val))
19 
21  struct boot_img_hdr {
22  ut8 magic[BOOT_MAGIC_SIZE];
23 
24  ut32 kernel_size; /* size in bytes */
25  ut32 kernel_addr; /* physical load addr */
26 
27  ut32 ramdisk_size; /* size in bytes */
28  ut32 ramdisk_addr; /* physical load addr */
29 
30  ut32 second_size; /* size in bytes */
31  ut32 second_addr; /* physical load addr */
32 
33  ut32 tags_addr; /* physical addr for kernel tags */
34  ut32 page_size; /* flash page size we assume */
35  ut32 unused[2]; /* future expansion: should be 0 */
36  ut8 name[BOOT_NAME_SIZE]; /* asciiz product name */
37  ut8 cmdline[BOOT_ARGS_SIZE];
38  ut32 id[8]; /* timestamp / checksum / sha1 / etc */
39 
40  /* Supplemental command line data; kept here to maintain
41  * binary compatibility with older versions of mkbootimg */
42  ut8 extra_cmdline[BOOT_EXTRA_ARGS_SIZE];
43  });
44 
45 typedef struct {
46  Sdb *kv;
49 } BootImageObj;
50 
51 static int bootimg_header_load(BootImageObj *obj, Sdb *db) {
52  char *n;
53  int i;
54  if (rz_buf_size(obj->buf) < sizeof(BootImage)) {
55  return false;
56  }
57  // TODO make it endian-safe (void)rz_buf_fread_at (buf, 0, (ut8*)bi, "IIiiiiiiiiiiii", 1);
58  BootImage *bi = &obj->bi;
59  (void)rz_buf_read_at(obj->buf, 0, (ut8 *)bi, sizeof(BootImage));
60  if ((n = rz_str_ndup((char *)bi->name, BOOT_NAME_SIZE))) {
61  sdb_set(db, "name", n, 0);
62  free(n);
63  }
64  if ((n = rz_str_ndup((char *)bi->cmdline, BOOT_ARGS_SIZE))) {
65  sdb_set(db, "cmdline", n, 0);
66  free(n);
67  }
68  for (i = 0; i < 8; i++) {
69  sdb_num_set(db, "id", (ut64)bi->id[i], 0);
70  }
71  if ((n = rz_str_ndup((char *)bi->extra_cmdline, BOOT_EXTRA_ARGS_SIZE))) {
72  sdb_set(db, "extra_cmdline", n, 0);
73  free(n);
74  }
75  return true;
76 }
77 
78 static Sdb *get_sdb(RzBinFile *bf) {
79  RzBinObject *o = bf->o;
80  BootImageObj *ao;
81  if (!o) {
82  return NULL;
83  }
84  ao = o->bin_obj;
85  return ao ? ao->kv : NULL;
86 }
87 
88 static bool load_buffer(RzBinFile *bf, RzBinObject *obj, RzBuffer *buf, Sdb *sdb) {
90  if (!bio) {
91  return false;
92  }
93  bio->kv = sdb_new0();
94  if (!bio->kv) {
95  free(bio);
96  return false;
97  }
98  bio->buf = rz_buf_ref(buf);
99  if (!bootimg_header_load(bio, bio->kv)) {
100  free(bio);
101  return false;
102  }
103  sdb_ns_set(sdb, "info", bio->kv);
104  obj->bin_obj = bio;
105  return true;
106 }
107 
108 static void destroy(RzBinFile *bf) {
109  BootImageObj *bio = bf->o->bin_obj;
110  rz_buf_free(bio->buf);
111  RZ_FREE(bf->o->bin_obj);
112 }
113 
114 static ut64 baddr(RzBinFile *bf) {
115  BootImageObj *bio = bf->o->bin_obj;
116  return bio ? bio->bi.kernel_addr : 0;
117 }
118 
119 static RzList *strings(RzBinFile *bf) {
120  return NULL;
121 }
122 
123 static RzBinInfo *info(RzBinFile *bf) {
124  RzBinInfo *ret;
125  if (!bf || !bf->o || !bf->o->bin_obj) {
126  return NULL;
127  }
128  ret = RZ_NEW0(RzBinInfo);
129  if (!ret) {
130  return NULL;
131  }
132 
133  ret->lang = NULL;
134  ret->file = bf->file ? strdup(bf->file) : NULL;
135  ret->type = strdup("Android Boot Image");
136  ret->os = strdup("android");
137  ret->subsystem = strdup("unknown");
138  ret->machine = strdup("arm");
139  ret->arch = strdup("arm");
140  ret->has_va = 1;
141  ret->has_pi = 0;
142  ret->bits = 16;
143  ret->big_endian = 0;
144  ret->dbg_info = 0;
145  ret->rclass = strdup("image");
146  return ret;
147 }
148 
149 static bool check_buffer(RzBuffer *buf) {
150  ut8 tmp[13];
151  int r = rz_buf_read_at(buf, 0, tmp, sizeof(tmp));
152  return r > 12 && !strncmp((const char *)tmp, "ANDROID!", 8);
153 }
154 
155 static RzList *entries(RzBinFile *bf) {
156  BootImageObj *bio = bf->o->bin_obj;
157  RzBinAddr *ptr = NULL;
158  if (!bio) {
159  return NULL;
160  }
161  BootImage *bi = &bio->bi;
162  RzList *ret;
163 
164  if (!(ret = rz_list_newf(free))) {
165  return NULL;
166  }
167  if (!(ptr = RZ_NEW0(RzBinAddr))) {
168  return ret;
169  }
170  ptr->paddr = bi->page_size;
171  ptr->vaddr = bi->kernel_addr;
172  rz_list_append(ret, ptr);
173  return ret;
174 }
175 
176 static RzList *sections(RzBinFile *bf) {
177  BootImageObj *bio = bf->o->bin_obj;
178  if (!bio) {
179  return NULL;
180  }
181  BootImage *bi = &bio->bi;
182  RzList *ret = NULL;
183  RzBinSection *ptr = NULL;
184 
185  if (!(ret = rz_list_new())) {
186  return NULL;
187  }
188  ret->free = free;
189 
190  if (!(ptr = RZ_NEW0(RzBinSection))) {
191  return ret;
192  }
193  ptr->name = strdup("header");
194  ptr->size = sizeof(BootImage);
195  ptr->vsize = bi->page_size;
196  ptr->paddr = 0;
197  ptr->vaddr = 0;
198  ptr->perm = RZ_PERM_R; // r--
199  rz_list_append(ret, ptr);
200 
201  if (!(ptr = RZ_NEW0(RzBinSection))) {
202  return ret;
203  }
204  ptr->name = strdup("kernel");
205  ptr->size = bi->kernel_size;
206  ptr->vsize = ADD_REMAINDER(ptr->size, bi->page_size);
207  ptr->paddr = bi->page_size;
208  ptr->vaddr = bi->kernel_addr;
209  ptr->perm = RZ_PERM_R; // r--
210  rz_list_append(ret, ptr);
211 
212  if (bi->ramdisk_size > 0) {
213  ut64 base = bi->kernel_size + 2 * bi->page_size - 1;
214  if (!(ptr = RZ_NEW0(RzBinSection))) {
215  return ret;
216  }
217  ptr->name = strdup("ramdisk");
218  ptr->size = bi->ramdisk_size;
219  ptr->vsize = ADD_REMAINDER(bi->ramdisk_size, bi->page_size);
220  ptr->paddr = ROUND_DOWN(base, bi->page_size);
221  ptr->vaddr = bi->ramdisk_addr;
222  ptr->perm = RZ_PERM_RX; // r-x
223  rz_list_append(ret, ptr);
224  }
225 
226  if (bi->second_size > 0) {
227  ut64 base = bi->kernel_size + bi->ramdisk_size + 2 * bi->page_size - 1;
228  if (!(ptr = RZ_NEW0(RzBinSection))) {
229  return ret;
230  }
231  ptr->name = strdup("second");
232  ptr->size = bi->second_size;
233  ptr->vsize = ADD_REMAINDER(bi->second_size, bi->page_size);
234  ptr->paddr = ROUND_DOWN(base, bi->page_size);
235  ptr->vaddr = bi->second_addr;
236  ptr->perm = RZ_PERM_RX; // r-x
237  rz_list_append(ret, ptr);
238  }
239 
240  return ret;
241 }
242 
244  .name = "bootimg",
245  .desc = "Android Boot Image",
246  .license = "LGPL3",
247  .get_sdb = &get_sdb,
248  .load_buffer = &load_buffer,
249  .destroy = &destroy,
250  .check_buffer = &check_buffer,
251  .baddr = &baddr,
253  .sections = &sections,
254  .entries = entries,
255  .strings = &strings,
256  .info = &info,
257 };
258 
259 #ifndef RZ_PLUGIN_INCORE
262  .data = &rz_bin_plugin_bootimg,
264 };
265 #endif
lzma_index ** i
Definition: index.h:629
RZ_API RZ_OWN RzList * rz_bin_maps_of_file_sections(RZ_NONNULL RzBinFile *binfile)
Create a list of RzBinMap from RzBinSections queried from the given file.
Definition: bin.c:1040
static Sdb * get_sdb(RzBinFile *bf)
Definition: bin_bootimg.c:78
#define BOOT_EXTRA_ARGS_SIZE
Definition: bin_bootimg.c:15
struct boot_img_hdr BootImage
Definition: bin_bootimg.c:9
static int bootimg_header_load(BootImageObj *obj, Sdb *db)
Definition: bin_bootimg.c:51
static bool check_buffer(RzBuffer *buf)
Definition: bin_bootimg.c:149
static bool load_buffer(RzBinFile *bf, RzBinObject *obj, RzBuffer *buf, Sdb *sdb)
Definition: bin_bootimg.c:88
#define BOOT_NAME_SIZE
Definition: bin_bootimg.c:13
RZ_PACKED(struct boot_img_hdr { ut8 magic[BOOT_MAGIC_SIZE];ut32 kernel_size;ut32 kernel_addr;ut32 ramdisk_size;ut32 ramdisk_addr;ut32 second_size;ut32 second_addr;ut32 tags_addr;ut32 page_size;ut32 unused[2];ut8 name[BOOT_NAME_SIZE];ut8 cmdline[BOOT_ARGS_SIZE];ut32 id[8];ut8 extra_cmdline[BOOT_EXTRA_ARGS_SIZE];})
#define BOOT_ARGS_SIZE
Definition: bin_bootimg.c:14
static RzList * strings(RzBinFile *bf)
Definition: bin_bootimg.c:119
static void destroy(RzBinFile *bf)
Definition: bin_bootimg.c:108
RZ_API RzLibStruct rizin_plugin
Definition: bin_bootimg.c:260
static RzBinInfo * info(RzBinFile *bf)
Definition: bin_bootimg.c:123
static ut64 baddr(RzBinFile *bf)
Definition: bin_bootimg.c:114
static RzList * entries(RzBinFile *bf)
Definition: bin_bootimg.c:155
RzBinPlugin rz_bin_plugin_bootimg
Definition: bin_bootimg.c:243
static RzList * sections(RzBinFile *bf)
Definition: bin_bootimg.c:176
#define ADD_REMAINDER(val, aln)
Definition: bin_bootimg.c:17
#define BOOT_MAGIC_SIZE
Definition: bin_bootimg.c:12
#define ROUND_DOWN(val, aln)
Definition: bin_bootimg.c:18
#define RZ_API
#define NULL
Definition: cris-opc.c:27
#define r
Definition: crypto_rc6.c:12
uint32_t ut32
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
voidpf void * buf
Definition: ioapi.h:138
uint8_t ut8
Definition: lh5801.h:11
RZ_API RZ_OWN RzList * rz_list_newf(RzListFree f)
Returns a new initialized RzList pointer and sets the free method.
Definition: list.c:248
RZ_API RZ_OWN RzList * rz_list_new(void)
Returns a new initialized RzList pointer (free method is not initialized)
Definition: list.c:235
RZ_API RZ_BORROW RzListIter * rz_list_append(RZ_NONNULL RzList *list, void *data)
Appends at the end of the list a new element.
Definition: list.c:288
return strdup("=SP r13\n" "=LR r14\n" "=PC r15\n" "=A0 r0\n" "=A1 r1\n" "=A2 r2\n" "=A3 r3\n" "=ZF zf\n" "=SF nf\n" "=OF vf\n" "=CF cf\n" "=SN or0\n" "gpr lr .32 56 0\n" "gpr pc .32 60 0\n" "gpr cpsr .32 64 0 ____tfiae_________________qvczn\n" "gpr or0 .32 68 0\n" "gpr tf .1 64.5 0 thumb\n" "gpr ef .1 64.9 0 endian\n" "gpr jf .1 64.24 0 java\n" "gpr qf .1 64.27 0 sticky_overflow\n" "gpr vf .1 64.28 0 overflow\n" "gpr cf .1 64.29 0 carry\n" "gpr zf .1 64.30 0 zero\n" "gpr nf .1 64.31 0 negative\n" "gpr itc .4 64.10 0 if_then_count\n" "gpr gef .4 64.16 0 great_or_equal\n" "gpr r0 .32 0 0\n" "gpr r1 .32 4 0\n" "gpr r2 .32 8 0\n" "gpr r3 .32 12 0\n" "gpr r4 .32 16 0\n" "gpr r5 .32 20 0\n" "gpr r6 .32 24 0\n" "gpr r7 .32 28 0\n" "gpr r8 .32 32 0\n" "gpr r9 .32 36 0\n" "gpr r10 .32 40 0\n" "gpr r11 .32 44 0\n" "gpr r12 .32 48 0\n" "gpr r13 .32 52 0\n" "gpr r14 .32 56 0\n" "gpr r15 .32 60 0\n" "gpr r16 .32 64 0\n" "gpr r17 .32 68 0\n")
int n
Definition: mipsasm.c:19
RZ_API int sdb_ns_set(Sdb *s, const char *name, Sdb *r)
Definition: ns.c:156
RZ_API int sdb_num_set(Sdb *s, const char *key, ut64 v, ut32 cas)
Definition: num.c:25
RZ_API RzBuffer * rz_buf_ref(RzBuffer *b)
Increment the reference count of the buffer.
Definition: buf.c:668
RZ_API st64 rz_buf_read_at(RZ_NONNULL RzBuffer *b, ut64 addr, RZ_NONNULL RZ_OUT ut8 *buf, ut64 len)
Read len bytes of the buffer at the specified address.
Definition: buf.c:1136
RZ_API void rz_buf_free(RzBuffer *b)
Free all internal data hold by the buffer and the buffer.
Definition: buf.c:1253
RZ_API ut64 rz_buf_size(RZ_NONNULL RzBuffer *b)
Return the size of the buffer.
Definition: buf.c:1225
@ RZ_LIB_TYPE_BIN
Definition: rz_lib.h:75
RZ_API char * rz_str_ndup(RZ_NULLABLE const char *ptr, int len)
Create new copy of string ptr limited to size len.
Definition: str.c:1006
#define RZ_PERM_R
Definition: rz_types.h:93
#define RZ_NEW0(x)
Definition: rz_types.h:284
#define RZ_PERM_RX
Definition: rz_types.h:97
#define RZ_FREE(x)
Definition: rz_types.h:369
#define RZ_VERSION
Definition: rz_version.h:8
RZ_API int sdb_set(Sdb *s, const char *key, const char *val, ut32 cas)
Definition: sdb.c:611
RZ_API Sdb * sdb_new0(void)
Definition: sdb.c:43
BootImage bi
Definition: bin_bootimg.c:47
RzBuffer * buf
Definition: bin_bootimg.c:48
Definition: z80asm.h:102
ut64 vaddr
Definition: rz_bin.h:186
ut64 paddr
Definition: rz_bin.h:187
XX curplugin == o->plugin.
Definition: rz_bin.h:298
RzBinObject * o
Definition: rz_bin.h:305
char * file
Definition: rz_bin.h:299
int has_va
Definition: rz_bin.h:228
char * type
Definition: rz_bin.h:211
char * os
Definition: rz_bin.h:219
char * subsystem
Definition: rz_bin.h:220
int has_pi
Definition: rz_bin.h:229
char * machine
Definition: rz_bin.h:216
const char * lang
Definition: rz_bin.h:224
char * file
Definition: rz_bin.h:210
ut64 dbg_info
Definition: rz_bin.h:240
char * rclass
Definition: rz_bin.h:213
char * arch
Definition: rz_bin.h:214
int big_endian
Definition: rz_bin.h:235
void * bin_obj
Definition: rz_bin.h:293
char * name
Definition: rz_bin.h:509
char * version
Definition: rz_bin.h:512
char * name
Definition: rz_bin.h:619
RzListFree free
Definition: rz_list.h:21
Definition: sdb.h:63
ut64(WINAPI *w32_GetEnabledXStateFeatures)()