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