1 /* ------------------------------------------------------------------------- */
2 /* */
3 /* Android Boot image extraction tool */
4 /* */
5 /* Copyright (C) 2012,2016 Chris Simmonds */
6 /* */
7 /* This program is free software; you can redistribute it and/or modify */
8 /* it under the terms of the GNU General Public License as published by */
9 /* the Free Software Foundation; either version 2 of the License, or */
10 /* (at your option) any later version. */
11 /* */
12 /* This program is distributed in the hope that it will be useful, */
13 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
14 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU */
15 /* General Public License for more details. */
16 /* */
17 /* You should have received a copy of the GNU General Public License */
18 /* along with this program; if not, write to the Free Software */
19 /* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
20 /* */
21 /* ------------------------------------------------------------------------- */
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <fcntl.h>
29 #include <unistd.h>
30 #include <errno.h>
31
32 /* bootimg.h is copied from AOSP:
33 Jelly Bean/4.2:
34 system/core/mkbootimg/bootimg.h
35 Earlier releases:
36 bootable/bootloader/legacy/include/boot/bootimg.h
37 */
38 #include "bootimg.h"
39
40 extern int optind;
41
usage(char * prog)42 static void usage(char *prog)
43 {
44 printf("\nAndroid boot image extraction tool v1.1\n"
45 "Copyright (C)2012,2016 Chris Simmonds\n\n"
46 "Usage %s <-i> [boot or recovery image file]\n"
47 " -i information only: do not extract images\n", prog);
48 exit(1);
49 }
50
main(int argc,char ** argv)51 int main(int argc, char **argv)
52 {
53 int opt;
54 int info_only = 0;
55 int f;
56 int fk;
57 int fr;
58 int n;
59 char *buf;
60 unsigned int flash_page_size;
61 struct boot_img_hdr hdr;
62
63 if (argc == 1)
64 usage(argv[0]);
65
66 while ((opt = getopt(argc, argv, "hi")) != -1) {
67 switch (opt) {
68 case 'i':
69 info_only = 1;
70 break;
71 case 'h':
72 usage(argv[0]);
73 default:
74 exit(1);
75 }
76 }
77 printf("argc %d optind %d\n", argc, optind);
78
79 if (optind == argc)
80 usage(argv[0]);
81
82 f = open(argv[optind], O_RDONLY);
83 if (f == -1) {
84 printf("Failed to open %s (%s)\n", argv[optind], strerror(errno));
85 return 1;
86 }
87
88 n = read(f, &hdr, sizeof(hdr));
89 if (n < sizeof(hdr)) {
90 printf("read failed\n");
91 return 1;
92 }
93
94 if (strncmp((const char *)hdr.magic, BOOT_MAGIC, BOOT_MAGIC_SIZE) != 0) {
95 printf("Boot magic missing or corrupt: not a valid boot image\n");
96 return 1;
97 }
98
99 printf("Boot header\n"
100 " flash page size\t%d\n"
101 " kernel size\t\t0x%x\n"
102 " kernel load addr\t0x%x\n"
103 " ramdisk size\t\t0x%x\n"
104 " ramdisk load addr\t0x%x\n"
105 " second size\t\t0x%x\n"
106 " second load addr\t0x%x\n"
107 " tags addr\t\t0x%x\n"
108 " product name\t\t'%s'\n"
109 " kernel cmdline\t'%s'\n\n",
110 hdr.page_size,
111 hdr.kernel_size, hdr.kernel_addr,
112 hdr.ramdisk_size, hdr.ramdisk_addr,
113 hdr.second_size, hdr.second_addr,
114 hdr.tags_addr, hdr.name, hdr.cmdline);
115
116 if (info_only)
117 return 0;
118
119 flash_page_size = hdr.page_size;
120 if (hdr.kernel_size > 0) {
121 /* extract kernel */
122 lseek(f, flash_page_size, SEEK_SET);
123 fk = open("zImage", O_WRONLY | O_CREAT | O_TRUNC, 0644);
124 if (fk < 0) {
125 printf("Failed to create kernel file\n");
126 return 1;
127 }
128 buf = malloc(hdr.kernel_size);
129 if (buf == 0) {
130 printf("malloc failed\n");
131 return 1;
132 }
133 n = read(f, buf, hdr.kernel_size);
134 if (n != hdr.kernel_size) {
135 printf ("Error in read\n");
136 return 1;
137 }
138 write(fk, buf, hdr.kernel_size);
139 free(buf);
140 close(fk);
141 printf("zImage extracted\n");
142 }
143
144 if (hdr.ramdisk_size > 0) {
145 int ramdisk_offset;
146
147 /* extract ramdisk */
148 ramdisk_offset =
149 (((hdr.kernel_size + flash_page_size -
150 1) / flash_page_size) + 1) * flash_page_size;
151 printf("ramdisk offset %d (0x%x)\n", ramdisk_offset,
152 ramdisk_offset);
153
154 lseek(f, ramdisk_offset, SEEK_SET);
155 fr = open("ramdisk.cpio.gz", O_WRONLY | O_CREAT | O_TRUNC, 0644);
156 if (fr < 0) {
157 printf("Failed to create ramdisk file\n");
158 return 1;
159 }
160 buf = malloc(hdr.ramdisk_size);
161 if (buf == 0) {
162 printf("malloc failed\n");
163 return 1;
164 }
165 n = read(f, buf, hdr.ramdisk_size);
166 if (n != hdr.ramdisk_size) {
167 printf ("Error in read\n");
168 return 1;
169 }
170 write(fr, buf, hdr.ramdisk_size);
171 free(buf);
172 close(fr);
173 printf("ramdisk.cpio.gz extracted\n");
174 }
175 if (hdr.second_size > 0) {
176 int second_offset;
177
178 /* extract second binary */
179 second_offset =
180 (((hdr.kernel_size + hdr.ramdisk_size + flash_page_size -
181 1) / flash_page_size) + 1) * flash_page_size;
182 printf("Second binary at offset %d (0x%x)\n", second_offset,
183 second_offset);
184
185 lseek(f, second_offset, SEEK_SET);
186 fr = open("second.dtb", O_WRONLY | O_CREAT | O_TRUNC, 0644);
187 if (fr < 0) {
188 printf("Failed to create second (dtb) file\n");
189 return 1;
190 }
191 buf = malloc(hdr.second_size);
192 if (buf == 0) {
193 printf("malloc failed\n");
194 return 1;
195 }
196 n = read(f, buf, hdr.second_size);
197 if (n != hdr.second_size) {
198 printf ("Error in read\n");
199 return 1;
200 }
201 write(fr, buf, hdr.second_size);
202 free(buf);
203 close(fr);
204 printf("second.dtb extracted\n");
205 }
206
207 return 0;
208 }
209