blob: 7c8f78b800860c76a3826643f11d3ac9c62a8e95 [file] [log] [blame]
Brian Swetland9c4c0752009-01-25 16:23:50 -08001/*
2 * Copyright (c) 2009, Google Inc.
3 * All rights reserved.
4 *
Ajay Dudanid04110c2011-01-17 23:55:07 -08005 * Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
Brian Swetland9c4c0752009-01-25 16:23:50 -08006 *
Chandan Uddaraju5fa471a2009-12-02 17:31:34 -08007 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * * Neither the name of Code Aurora nor
15 * the names of its contributors may be used to endorse or promote
16 * products derived from this software without specific prior written
17 * permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 *
Brian Swetland9c4c0752009-01-25 16:23:50 -080031 */
32
33#include <app.h>
34#include <debug.h>
35#include <arch/arm.h>
36#include <dev/udc.h>
37#include <string.h>
38#include <kernel/thread.h>
39#include <arch/ops.h>
40
Dima Zavin214cc642009-01-26 11:16:21 -080041#include <dev/flash.h>
42#include <lib/ptable.h>
Dima Zavinb4283602009-01-26 16:36:57 -080043#include <dev/keys.h>
Shashank Mittal4f99a882010-02-01 13:58:50 -080044#include <dev/fbcon.h>
Ajay Dudanid04110c2011-01-17 23:55:07 -080045#include <baseband.h>
Greg Griscod6250552011-06-29 14:40:23 -070046#include <target.h>
47#include <mmc.h>
Kinson Chikf1a43512011-07-14 11:28:39 -070048#include <partition_parser.h>
Greg Griscod6250552011-06-29 14:40:23 -070049#include <platform.h>
Shashank Mittalcd98d472011-08-02 14:29:24 -070050#include <crypto_hash.h>
Dima Zavin214cc642009-01-26 11:16:21 -080051
Shashank Mittalcd98d472011-08-02 14:29:24 -070052#include "image_verify.h"
Shashank Mittal024c0332010-02-03 11:44:00 -080053#include "recovery.h"
Brian Swetland9c4c0752009-01-25 16:23:50 -080054#include "bootimg.h"
55#include "fastboot.h"
Ajay Dudani5c761132011-04-07 20:19:04 -070056#include "sparse_format.h"
Greg Grisco6e754772011-06-23 12:19:39 -070057#include "mmc.h"
Shashank Mittal162244e2011-08-08 19:01:25 -070058#include "devinfo.h"
Brian Swetland9c4c0752009-01-25 16:23:50 -080059
Shashank Mittal162244e2011-08-08 19:01:25 -070060#include "scm.h"
kchik@codeaurora.orgbce18ea2011-04-18 20:22:28 -070061
Subbaraman Narayanamurthyeb92bcc2010-07-20 14:32:46 -070062#define EXPAND(NAME) #NAME
63#define TARGET(NAME) EXPAND(NAME)
Chandan Uddarajuda919832009-11-17 01:06:11 -080064#define DEFAULT_CMDLINE "mem=100M console=null";
Brian Swetland2defe162009-08-18 14:35:59 -070065
Ajay Dudanicd01f9b2010-02-23 21:13:04 -080066#ifdef MEMBASE
67#define EMMC_BOOT_IMG_HEADER_ADDR (0xFF000+(MEMBASE))
68#else
David Ng183a7422009-12-07 14:55:21 -080069#define EMMC_BOOT_IMG_HEADER_ADDR 0xFF000
Ajay Dudanicd01f9b2010-02-23 21:13:04 -080070#endif
71
Chandan Uddarajude85d3f2010-01-05 16:32:33 -080072#define RECOVERY_MODE 0x77665502
73#define FASTBOOT_MODE 0x77665500
74
David Ng183a7422009-12-07 14:55:21 -080075static const char *emmc_cmdline = " androidboot.emmc=true";
Subbaraman Narayanamurthyf17b4ae2011-02-16 20:19:56 -080076static const char *usb_sn_cmdline = " androidboot.serialno=";
Ajay Dudanica3a33c2011-11-18 08:31:40 -080077static const char *battchg_pause = " androidboot.mode=charger";
Shashank Mittalcd98d472011-08-02 14:29:24 -070078static const char *auth_kernel = " androidboot.authorized_kernel=true";
David Ng183a7422009-12-07 14:55:21 -080079
Ajay Dudani6cff85e2011-02-04 16:02:16 -080080static const char *baseband_apq = " androidboot.baseband=apq";
81static const char *baseband_msm = " androidboot.baseband=msm";
82static const char *baseband_csfb = " androidboot.baseband=csfb";
83static const char *baseband_svlte2a = " androidboot.baseband=svlte2a";
Ajay Dudani403bc492011-09-30 16:17:21 -070084static const char *baseband_mdm = " androidboot.baseband=mdm";
Ajay Dudanid04110c2011-01-17 23:55:07 -080085
Shashank Mittalcd98d472011-08-02 14:29:24 -070086/* Assuming unauthorized kernel image by default */
87static int auth_kernel_img = 0;
88
Shashank Mittal162244e2011-08-08 19:01:25 -070089static device_info device = {DEVICE_MAGIC, 0, 0};
90
Brian Swetland9c4c0752009-01-25 16:23:50 -080091static struct udc_device surf_udc_device = {
92 .vendor_id = 0x18d1,
Chandan Uddarajuc53a1a12009-11-18 14:53:40 -080093 .product_id = 0xD00D,
Brian Swetland9c4c0752009-01-25 16:23:50 -080094 .version_id = 0x0100,
95 .manufacturer = "Google",
96 .product = "Android",
97};
98
Dima Zavin42168f22009-01-30 11:52:22 -080099struct atag_ptbl_entry
100{
101 char name[16];
102 unsigned offset;
103 unsigned size;
104 unsigned flags;
105};
106
Subbaraman Narayanamurthyf17b4ae2011-02-16 20:19:56 -0800107char sn_buf[13];
Greg Griscod6250552011-06-29 14:40:23 -0700108
Greg Griscod2471ef2011-07-14 13:00:42 -0700109extern int emmc_recovery_init(void);
110
Kinson Chik0b1c8162011-08-31 16:31:57 -0700111#if NO_KEYPAD_DRIVER
112extern int fastboot_trigger(void);
113#endif
Greg Griscod2471ef2011-07-14 13:00:42 -0700114
Dima Zavin42168f22009-01-30 11:52:22 -0800115static void ptentry_to_tag(unsigned **ptr, struct ptentry *ptn)
116{
117 struct atag_ptbl_entry atag_ptn;
118
119 memcpy(atag_ptn.name, ptn->name, 16);
120 atag_ptn.name[15] = '\0';
121 atag_ptn.offset = ptn->start;
122 atag_ptn.size = ptn->length;
123 atag_ptn.flags = ptn->flags;
124 memcpy(*ptr, &atag_ptn, sizeof(struct atag_ptbl_entry));
125 *ptr += sizeof(struct atag_ptbl_entry) / sizeof(unsigned);
126}
Brian Swetland9c4c0752009-01-25 16:23:50 -0800127
kchik@codeaurora.orgbce18ea2011-04-18 20:22:28 -0700128void boot_linux(void *kernel, unsigned *tags,
Brian Swetland9c4c0752009-01-25 16:23:50 -0800129 const char *cmdline, unsigned machtype,
130 void *ramdisk, unsigned ramdisk_size)
131{
132 unsigned *ptr = tags;
Shashank Mittal8e49dec2010-03-01 15:19:04 -0800133 unsigned pcount = 0;
Brian Swetland9c4c0752009-01-25 16:23:50 -0800134 void (*entry)(unsigned,unsigned,unsigned*) = kernel;
Dima Zavin42168f22009-01-30 11:52:22 -0800135 struct ptable *ptable;
David Ng183a7422009-12-07 14:55:21 -0800136 int cmdline_len = 0;
137 int have_cmdline = 0;
David Ngf773dde2010-07-26 19:55:08 -0700138 int pause_at_bootup = 0;
Brian Swetland9c4c0752009-01-25 16:23:50 -0800139
140 /* CORE */
141 *ptr++ = 2;
142 *ptr++ = 0x54410001;
143
144 if (ramdisk_size) {
145 *ptr++ = 4;
146 *ptr++ = 0x54420005;
Dima Zavin214cc642009-01-26 11:16:21 -0800147 *ptr++ = (unsigned)ramdisk;
Brian Swetland9c4c0752009-01-25 16:23:50 -0800148 *ptr++ = ramdisk_size;
149 }
150
Chandan Uddarajuc6860e12009-11-19 11:22:15 -0800151 ptr = target_atag_mem(ptr);
152
David Ng183a7422009-12-07 14:55:21 -0800153 if (!target_is_emmc_boot()) {
154 /* Skip NAND partition ATAGS for eMMC boot */
155 if ((ptable = flash_get_ptable()) && (ptable->count != 0)) {
156 int i;
Mekala Natarajanc43d8842011-10-26 15:09:10 -0700157 *ptr++ = 2 + (ptable->count * (sizeof(struct atag_ptbl_entry) /
David Ng183a7422009-12-07 14:55:21 -0800158 sizeof(unsigned)));
159 *ptr++ = 0x4d534d70;
160 for (i = 0; i < ptable->count; ++i)
161 ptentry_to_tag(&ptr, ptable_get(ptable, i));
162 }
Dima Zavin42168f22009-01-30 11:52:22 -0800163 }
164
Brian Swetland9c4c0752009-01-25 16:23:50 -0800165 if (cmdline && cmdline[0]) {
David Ng183a7422009-12-07 14:55:21 -0800166 cmdline_len = strlen(cmdline);
167 have_cmdline = 1;
168 }
169 if (target_is_emmc_boot()) {
170 cmdline_len += strlen(emmc_cmdline);
171 }
Subbaraman Narayanamurthyf17b4ae2011-02-16 20:19:56 -0800172
173 cmdline_len += strlen(usb_sn_cmdline);
174 cmdline_len += strlen(sn_buf);
175
David Ngf773dde2010-07-26 19:55:08 -0700176 if (target_pause_for_battery_charge()) {
177 pause_at_bootup = 1;
178 cmdline_len += strlen(battchg_pause);
179 }
Ajay Dudanid04110c2011-01-17 23:55:07 -0800180
Shashank Mittalcd98d472011-08-02 14:29:24 -0700181 if(target_use_signed_kernel() && auth_kernel_img) {
182 cmdline_len += strlen(auth_kernel);
183 }
184
Ajay Dudanid04110c2011-01-17 23:55:07 -0800185 /* Determine correct androidboot.baseband to use */
186 switch(target_baseband())
187 {
188 case BASEBAND_APQ:
189 cmdline_len += strlen(baseband_apq);
190 break;
191
192 case BASEBAND_MSM:
193 cmdline_len += strlen(baseband_msm);
194 break;
195
196 case BASEBAND_CSFB:
197 cmdline_len += strlen(baseband_csfb);
198 break;
199
Ajay Dudani6cff85e2011-02-04 16:02:16 -0800200 case BASEBAND_SVLTE2A:
201 cmdline_len += strlen(baseband_svlte2a);
Ajay Dudanid04110c2011-01-17 23:55:07 -0800202 break;
Ajay Dudani403bc492011-09-30 16:17:21 -0700203
204 case BASEBAND_MDM:
205 cmdline_len += strlen(baseband_mdm);
206 break;
Ajay Dudanid04110c2011-01-17 23:55:07 -0800207 }
208
David Ng183a7422009-12-07 14:55:21 -0800209 if (cmdline_len > 0) {
210 const char *src;
211 char *dst;
Brian Swetland9c4c0752009-01-25 16:23:50 -0800212 unsigned n;
213 /* include terminating 0 and round up to a word multiple */
David Ng183a7422009-12-07 14:55:21 -0800214 n = (cmdline_len + 4) & (~3);
Brian Swetland9c4c0752009-01-25 16:23:50 -0800215 *ptr++ = (n / 4) + 2;
216 *ptr++ = 0x54410009;
David Ng183a7422009-12-07 14:55:21 -0800217 dst = (char *)ptr;
218 if (have_cmdline) {
219 src = cmdline;
220 while ((*dst++ = *src++));
221 }
222 if (target_is_emmc_boot()) {
223 src = emmc_cmdline;
224 if (have_cmdline) --dst;
David Ngf773dde2010-07-26 19:55:08 -0700225 have_cmdline = 1;
226 while ((*dst++ = *src++));
227 }
Subbaraman Narayanamurthyf17b4ae2011-02-16 20:19:56 -0800228
229 src = usb_sn_cmdline;
230 if (have_cmdline) --dst;
231 have_cmdline = 1;
232 while ((*dst++ = *src++));
233 src = sn_buf;
234 if (have_cmdline) --dst;
235 have_cmdline = 1;
236 while ((*dst++ = *src++));
237
David Ngf773dde2010-07-26 19:55:08 -0700238 if (pause_at_bootup) {
239 src = battchg_pause;
240 if (have_cmdline) --dst;
David Ng183a7422009-12-07 14:55:21 -0800241 while ((*dst++ = *src++));
242 }
Ajay Dudanid04110c2011-01-17 23:55:07 -0800243
Shashank Mittalcd98d472011-08-02 14:29:24 -0700244 if(target_use_signed_kernel() && auth_kernel_img) {
245 src = auth_kernel;
246 if (have_cmdline) --dst;
247 while ((*dst++ = *src++));
248 }
249
Ajay Dudanid04110c2011-01-17 23:55:07 -0800250 switch(target_baseband())
251 {
252 case BASEBAND_APQ:
253 src = baseband_apq;
254 if (have_cmdline) --dst;
255 while ((*dst++ = *src++));
256 break;
257
258 case BASEBAND_MSM:
259 src = baseband_msm;
260 if (have_cmdline) --dst;
261 while ((*dst++ = *src++));
262 break;
263
264 case BASEBAND_CSFB:
265 src = baseband_csfb;
266 if (have_cmdline) --dst;
267 while ((*dst++ = *src++));
268 break;
269
Ajay Dudani6cff85e2011-02-04 16:02:16 -0800270 case BASEBAND_SVLTE2A:
271 src = baseband_svlte2a;
Ajay Dudanid04110c2011-01-17 23:55:07 -0800272 if (have_cmdline) --dst;
273 while ((*dst++ = *src++));
274 break;
Ajay Dudani403bc492011-09-30 16:17:21 -0700275
276 case BASEBAND_MDM:
277 src = baseband_mdm;
278 if (have_cmdline) --dst;
279 while ((*dst++ = *src++));
280 break;
Ajay Dudanid04110c2011-01-17 23:55:07 -0800281 }
Brian Swetland9c4c0752009-01-25 16:23:50 -0800282 ptr += (n / 4);
283 }
284
285 /* END */
286 *ptr++ = 0;
287 *ptr++ = 0;
288
289 dprintf(INFO, "booting linux @ %p, ramdisk @ %p (%d)\n",
290 kernel, ramdisk, ramdisk_size);
291 if (cmdline)
292 dprintf(INFO, "cmdline: %s\n", cmdline);
293
294 enter_critical_section();
Amol Jadi4421e652011-06-16 15:00:48 -0700295 /* do any platform specific cleanup before kernel entry */
296 platform_uninit();
Brian Swetland9c4c0752009-01-25 16:23:50 -0800297 arch_disable_cache(UCACHE);
Brian Swetland9c4c0752009-01-25 16:23:50 -0800298 arch_disable_mmu();
Brian Swetland9c4c0752009-01-25 16:23:50 -0800299 entry(0, machtype, tags);
Brian Swetland9c4c0752009-01-25 16:23:50 -0800300}
301
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800302unsigned page_size = 0;
303unsigned page_mask = 0;
Brian Swetland9c4c0752009-01-25 16:23:50 -0800304
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800305#define ROUND_TO_PAGE(x,y) (((x) + (y)) & (~(y)))
Brian Swetland9c4c0752009-01-25 16:23:50 -0800306
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800307static unsigned char buf[4096]; //Equal to max-supported pagesize
Dima Zavin214cc642009-01-26 11:16:21 -0800308
Shashank Mittal23b8f422010-04-16 19:27:21 -0700309int boot_linux_from_mmc(void)
310{
311 struct boot_img_hdr *hdr = (void*) buf;
312 struct boot_img_hdr *uhdr;
313 unsigned offset = 0;
314 unsigned long long ptn = 0;
315 unsigned n = 0;
316 const char *cmdline;
Kinson Chikf1a43512011-07-14 11:28:39 -0700317 int index = INVALID_PTN;
Shashank Mittal23b8f422010-04-16 19:27:21 -0700318
Shashank Mittalcd98d472011-08-02 14:29:24 -0700319 unsigned char *image_addr = 0;
320 unsigned kernel_actual;
321 unsigned ramdisk_actual;
322 unsigned imagesize_actual;
323
Shashank Mittal23b8f422010-04-16 19:27:21 -0700324 uhdr = (struct boot_img_hdr *)EMMC_BOOT_IMG_HEADER_ADDR;
325 if (!memcmp(uhdr->magic, BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
326 dprintf(INFO, "Unified boot method!\n");
327 hdr = uhdr;
328 goto unified_boot;
329 }
Greg Griscod6250552011-06-29 14:40:23 -0700330 if (!boot_into_recovery) {
Kinson Chikf1a43512011-07-14 11:28:39 -0700331 index = partition_get_index("boot");
332 ptn = partition_get_offset(index);
333 if(ptn == 0) {
Shashank Mittal85b91f62010-10-30 10:12:38 -0700334 dprintf(CRITICAL, "ERROR: No boot partition found\n");
335 return -1;
336 }
Kinson Chikf1a43512011-07-14 11:28:39 -0700337 }
338 else {
339 index = partition_get_index("recovery");
340 ptn = partition_get_offset(index);
341 if(ptn == 0) {
Shashank Mittal85b91f62010-10-30 10:12:38 -0700342 dprintf(CRITICAL, "ERROR: No recovery partition found\n");
343 return -1;
344 }
Shashank Mittal23b8f422010-04-16 19:27:21 -0700345 }
346
Greg Griscod6250552011-06-29 14:40:23 -0700347 if (mmc_read(ptn + offset, (unsigned int *) buf, page_size)) {
Shashank Mittal23b8f422010-04-16 19:27:21 -0700348 dprintf(CRITICAL, "ERROR: Cannot read boot image header\n");
349 return -1;
350 }
Shashank Mittal23b8f422010-04-16 19:27:21 -0700351
352 if (memcmp(hdr->magic, BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
Kinson Chik kchik@codeaurora.org82e4ae62011-04-12 17:42:07 -0700353 dprintf(CRITICAL, "ERROR: Invalid boot image header\n");
Shashank Mittal23b8f422010-04-16 19:27:21 -0700354 return -1;
355 }
356
Subbaraman Narayanamurthyfbe13a02010-09-10 11:51:12 -0700357 if (hdr->page_size && (hdr->page_size != page_size)) {
358 page_size = hdr->page_size;
359 page_mask = page_size - 1;
Shashank Mittal23b8f422010-04-16 19:27:21 -0700360 }
361
Shashank Mittalcd98d472011-08-02 14:29:24 -0700362 /* Authenticate Kernel */
Shashank Mittala0032282011-08-26 14:50:11 -0700363 if(target_use_signed_kernel() && (!device.is_unlocked) && (!device.is_tampered))
Subbaraman Narayanamurthy958fa242011-01-27 17:42:38 -0800364 {
Shashank Mittalcd98d472011-08-02 14:29:24 -0700365 image_addr = (unsigned char *)target_get_scratch_address();
366 kernel_actual = ROUND_TO_PAGE(hdr->kernel_size, page_mask);
367 ramdisk_actual = ROUND_TO_PAGE(hdr->ramdisk_size, page_mask);
368 imagesize_actual = (page_size + kernel_actual + ramdisk_actual);
369
370 offset = 0;
Shashank Mittal162244e2011-08-08 19:01:25 -0700371
372 /* Assuming device rooted at this time */
Shashank Mittala0032282011-08-26 14:50:11 -0700373 device.is_tampered = 1;
Shashank Mittal162244e2011-08-08 19:01:25 -0700374
Shashank Mittalcd98d472011-08-02 14:29:24 -0700375 /* Read image without signature */
376 if (mmc_read(ptn + offset, (void *)image_addr, imagesize_actual))
377 {
378 dprintf(CRITICAL, "ERROR: Cannot read boot image\n");
379 return -1;
Subbaraman Narayanamurthy958fa242011-01-27 17:42:38 -0800380 }
Shashank Mittalcd98d472011-08-02 14:29:24 -0700381
382 offset = imagesize_actual;
383 /* Read signature */
384 if(mmc_read(ptn + offset, (void *)(image_addr + offset), page_size))
385 {
386 dprintf(CRITICAL, "ERROR: Cannot read boot image signature\n");
387 }
388 else
389 {
390 auth_kernel_img = image_verify((unsigned char *)image_addr,
391 (unsigned char *)(image_addr + imagesize_actual),
392 imagesize_actual,
393 CRYPTO_AUTH_ALG_SHA256);
Shashank Mittal162244e2011-08-08 19:01:25 -0700394
395 if(auth_kernel_img)
396 {
397 /* Authorized kernel */
Shashank Mittala0032282011-08-26 14:50:11 -0700398 device.is_tampered = 0;
Shashank Mittal162244e2011-08-08 19:01:25 -0700399 }
Shashank Mittalcd98d472011-08-02 14:29:24 -0700400 }
401
402 /* Move kernel and ramdisk to correct address */
403 memmove((void*) hdr->kernel_addr, (char *)(image_addr + page_size), hdr->kernel_size);
404 memmove((void*) hdr->ramdisk_addr, (char *)(image_addr + page_size + kernel_actual), hdr->ramdisk_size);
Shashank Mittal162244e2011-08-08 19:01:25 -0700405
406 /* Make sure everything from scratch address is read before next step!*/
Shashank Mittala0032282011-08-26 14:50:11 -0700407 if(device.is_tampered)
Shashank Mittal162244e2011-08-08 19:01:25 -0700408 {
409 write_device_info_mmc(&device);
410 #ifdef TZ_TAMPER_FUSE
411 set_tamper_fuse_cmd();
412 #endif
413 }
Shashank Mittal23b8f422010-04-16 19:27:21 -0700414 }
Shashank Mittalcd98d472011-08-02 14:29:24 -0700415 else
416 {
417 offset += page_size;
418
419 n = ROUND_TO_PAGE(hdr->kernel_size, page_mask);
420 if (mmc_read(ptn + offset, (void *)hdr->kernel_addr, n)) {
421 dprintf(CRITICAL, "ERROR: Cannot read kernel image\n");
422 return -1;
423 }
424 offset += n;
425
426 n = ROUND_TO_PAGE(hdr->ramdisk_size, page_mask);
427 if(n != 0)
428 {
429 if (mmc_read(ptn + offset, (void *)hdr->ramdisk_addr, n)) {
430 dprintf(CRITICAL, "ERROR: Cannot read ramdisk image\n");
431 return -1;
432 }
433 }
434 offset += n;
435 }
Shashank Mittal23b8f422010-04-16 19:27:21 -0700436
437unified_boot:
438 dprintf(INFO, "\nkernel @ %x (%d bytes)\n", hdr->kernel_addr,
439 hdr->kernel_size);
440 dprintf(INFO, "ramdisk @ %x (%d bytes)\n", hdr->ramdisk_addr,
441 hdr->ramdisk_size);
442
443 if(hdr->cmdline[0]) {
444 cmdline = (char*) hdr->cmdline;
445 } else {
446 cmdline = DEFAULT_CMDLINE;
447 }
448 dprintf(INFO, "cmdline = '%s'\n", cmdline);
449
450 dprintf(INFO, "\nBooting Linux\n");
Greg Griscod2471ef2011-07-14 13:00:42 -0700451 boot_linux((void *)hdr->kernel_addr, (unsigned *) hdr->tags_addr,
Shashank Mittal23b8f422010-04-16 19:27:21 -0700452 (const char *)cmdline, board_machtype(),
453 (void *)hdr->ramdisk_addr, hdr->ramdisk_size);
454
455 return 0;
456}
457
Dima Zavin214cc642009-01-26 11:16:21 -0800458int boot_linux_from_flash(void)
459{
460 struct boot_img_hdr *hdr = (void*) buf;
461 unsigned n;
462 struct ptentry *ptn;
463 struct ptable *ptable;
464 unsigned offset = 0;
465 const char *cmdline;
Chandan Uddarajude85d3f2010-01-05 16:32:33 -0800466
Shashank Mittalcd98d472011-08-02 14:29:24 -0700467 unsigned char *image_addr = 0;
468 unsigned kernel_actual;
469 unsigned ramdisk_actual;
470 unsigned imagesize_actual;
471
David Ng183a7422009-12-07 14:55:21 -0800472 if (target_is_emmc_boot()) {
473 hdr = (struct boot_img_hdr *)EMMC_BOOT_IMG_HEADER_ADDR;
474 if (memcmp(hdr->magic, BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
475 dprintf(CRITICAL, "ERROR: Invalid boot image header\n");
476 return -1;
477 }
478 goto continue_boot;
479 }
480
Dima Zavin214cc642009-01-26 11:16:21 -0800481 ptable = flash_get_ptable();
482 if (ptable == NULL) {
483 dprintf(CRITICAL, "ERROR: Partition table not found\n");
484 return -1;
485 }
486
Chandan Uddarajude85d3f2010-01-05 16:32:33 -0800487 if(!boot_into_recovery)
488 {
489 ptn = ptable_find(ptable, "boot");
490 if (ptn == NULL) {
491 dprintf(CRITICAL, "ERROR: No boot partition found\n");
492 return -1;
493 }
494 }
495 else
496 {
497 ptn = ptable_find(ptable, "recovery");
498 if (ptn == NULL) {
499 dprintf(CRITICAL, "ERROR: No recovery partition found\n");
500 return -1;
501 }
Dima Zavin214cc642009-01-26 11:16:21 -0800502 }
503
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800504 if (flash_read(ptn, offset, buf, page_size)) {
Dima Zavin214cc642009-01-26 11:16:21 -0800505 dprintf(CRITICAL, "ERROR: Cannot read boot image header\n");
506 return -1;
507 }
Dima Zavin214cc642009-01-26 11:16:21 -0800508
509 if (memcmp(hdr->magic, BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
Kinson Chik kchik@codeaurora.org82e4ae62011-04-12 17:42:07 -0700510 dprintf(CRITICAL, "ERROR: Invalid boot image header\n");
Dima Zavin214cc642009-01-26 11:16:21 -0800511 return -1;
512 }
513
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800514 if (hdr->page_size != page_size) {
Kinson Chik kchik@codeaurora.org82e4ae62011-04-12 17:42:07 -0700515 dprintf(CRITICAL, "ERROR: Invalid boot image pagesize. Device pagesize: %d, Image pagesize: %d\n",page_size,hdr->page_size);
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800516 return -1;
517 }
518
Shashank Mittalcd98d472011-08-02 14:29:24 -0700519 /* Authenticate Kernel */
Shashank Mittala0032282011-08-26 14:50:11 -0700520 if(target_use_signed_kernel() && (!device.is_unlocked) && (!device.is_tampered))
Shashank Mittalcd98d472011-08-02 14:29:24 -0700521 {
522 image_addr = (unsigned char *)target_get_scratch_address();
523 kernel_actual = ROUND_TO_PAGE(hdr->kernel_size, page_mask);
524 ramdisk_actual = ROUND_TO_PAGE(hdr->ramdisk_size, page_mask);
525 imagesize_actual = (page_size + kernel_actual + ramdisk_actual);
Dima Zavin214cc642009-01-26 11:16:21 -0800526
Shashank Mittalcd98d472011-08-02 14:29:24 -0700527 offset = 0;
Shashank Mittal162244e2011-08-08 19:01:25 -0700528
529 /* Assuming device rooted at this time */
Shashank Mittala0032282011-08-26 14:50:11 -0700530 device.is_tampered = 1;
Shashank Mittal162244e2011-08-08 19:01:25 -0700531
Shashank Mittalcd98d472011-08-02 14:29:24 -0700532 /* Read image without signature */
533 if (flash_read(ptn, offset, (void *)image_addr, imagesize_actual))
534 {
535 dprintf(CRITICAL, "ERROR: Cannot read boot image\n");
536 return -1;
537 }
Dima Zavin214cc642009-01-26 11:16:21 -0800538
Shashank Mittalcd98d472011-08-02 14:29:24 -0700539 offset = imagesize_actual;
540 /* Read signature */
541 if (flash_read(ptn, offset, (void *)(image_addr + offset), page_size))
542 {
543 dprintf(CRITICAL, "ERROR: Cannot read boot image signature\n");
544 }
545 else
546 {
547
548 /* Verify signature */
549 auth_kernel_img = image_verify((unsigned char *)image_addr,
550 (unsigned char *)(image_addr + imagesize_actual),
551 imagesize_actual,
552 CRYPTO_AUTH_ALG_SHA256);
Shashank Mittal162244e2011-08-08 19:01:25 -0700553
554 if(auth_kernel_img)
555 {
556 /* Authorized kernel */
Shashank Mittala0032282011-08-26 14:50:11 -0700557 device.is_tampered = 0;
Shashank Mittal162244e2011-08-08 19:01:25 -0700558 }
Shashank Mittalcd98d472011-08-02 14:29:24 -0700559 }
560
561 /* Move kernel and ramdisk to correct address */
562 memmove((void*) hdr->kernel_addr, (char *)(image_addr + page_size), hdr->kernel_size);
563 memmove((void*) hdr->ramdisk_addr, (char *)(image_addr + page_size + kernel_actual), hdr->ramdisk_size);
Shashank Mittal162244e2011-08-08 19:01:25 -0700564
565 /* Make sure everything from scratch address is read before next step!*/
Shashank Mittala0032282011-08-26 14:50:11 -0700566 if(device.is_tampered)
Shashank Mittal162244e2011-08-08 19:01:25 -0700567 {
568 write_device_info_flash(&device);
569 }
Channagoud Kadabi5c86fe32012-02-16 10:58:48 +0530570#if USE_PCOM_SECBOOT
571 set_tamper_flag(device.is_tampered);
572#endif
Shashank Mittalcd98d472011-08-02 14:29:24 -0700573 }
574 else
575 {
Shashank Mittal162244e2011-08-08 19:01:25 -0700576 offset = page_size;
577
Shashank Mittalcd98d472011-08-02 14:29:24 -0700578 n = ROUND_TO_PAGE(hdr->kernel_size, page_mask);
579 if (flash_read(ptn, offset, (void *)hdr->kernel_addr, n)) {
580 dprintf(CRITICAL, "ERROR: Cannot read kernel image\n");
581 return -1;
582 }
583 offset += n;
584
585 n = ROUND_TO_PAGE(hdr->ramdisk_size, page_mask);
586 if (flash_read(ptn, offset, (void *)hdr->ramdisk_addr, n)) {
587 dprintf(CRITICAL, "ERROR: Cannot read ramdisk image\n");
588 return -1;
589 }
590 offset += n;
591 }
David Ng183a7422009-12-07 14:55:21 -0800592continue_boot:
Dima Zavin214cc642009-01-26 11:16:21 -0800593 dprintf(INFO, "\nkernel @ %x (%d bytes)\n", hdr->kernel_addr,
594 hdr->kernel_size);
595 dprintf(INFO, "ramdisk @ %x (%d bytes)\n", hdr->ramdisk_addr,
596 hdr->ramdisk_size);
597
598 if(hdr->cmdline[0]) {
599 cmdline = (char*) hdr->cmdline;
600 } else {
601 cmdline = DEFAULT_CMDLINE;
602 }
603 dprintf(INFO, "cmdline = '%s'\n", cmdline);
604
605 /* TODO: create/pass atags to kernel */
606
607 dprintf(INFO, "\nBooting Linux\n");
Ajay Dudanie28a6072011-07-01 13:59:46 -0700608 boot_linux((void *)hdr->kernel_addr, (void *)hdr->tags_addr,
Chandan Uddaraju885e4db2009-12-03 22:45:26 -0800609 (const char *)cmdline, board_machtype(),
Dima Zavin214cc642009-01-26 11:16:21 -0800610 (void *)hdr->ramdisk_addr, hdr->ramdisk_size);
611
612 return 0;
613}
Brian Swetland9c4c0752009-01-25 16:23:50 -0800614
Shashank Mittal162244e2011-08-08 19:01:25 -0700615unsigned char info_buf[4096];
616void write_device_info_mmc(device_info *dev)
617{
618 struct device_info *info = (void*) info_buf;
619 unsigned long long ptn = 0;
620 unsigned long long size;
621 int index = INVALID_PTN;
622
623 index = partition_get_index("aboot");
624 ptn = partition_get_offset(index);
625 if(ptn == 0)
626 {
627 return;
628 }
629
630 size = partition_get_size(index);
631
632 memcpy(info, dev, sizeof(device_info));
633
634 if(mmc_write((ptn + size - 512), 512, (void *)info_buf))
635 {
636 dprintf(CRITICAL, "ERROR: Cannot write device info\n");
637 return;
638 }
639}
640
641void read_device_info_mmc(device_info *dev)
642{
643 struct device_info *info = (void*) info_buf;
644 unsigned long long ptn = 0;
645 unsigned long long size;
646 int index = INVALID_PTN;
647
648 index = partition_get_index("aboot");
649 ptn = partition_get_offset(index);
650 if(ptn == 0)
651 {
652 return;
653 }
654
655 size = partition_get_size(index);
656
657 if(mmc_read((ptn + size - 512), (void *)info_buf, 512))
658 {
659 dprintf(CRITICAL, "ERROR: Cannot read device info\n");
660 return;
661 }
662
663 if (memcmp(info->magic, DEVICE_MAGIC, DEVICE_MAGIC_SIZE))
664 {
665 memcpy(info->magic, DEVICE_MAGIC, DEVICE_MAGIC_SIZE);
666 info->is_unlocked = 0;
Shashank Mittala0032282011-08-26 14:50:11 -0700667 info->is_tampered = 0;
Shashank Mittal162244e2011-08-08 19:01:25 -0700668
669 write_device_info_mmc(info);
670 }
671 memcpy(dev, info, sizeof(device_info));
672}
673
674void write_device_info_flash(device_info *dev)
675{
676 struct device_info *info = (void *) info_buf;
677 struct ptentry *ptn;
678 struct ptable *ptable;
679
680 ptable = flash_get_ptable();
681 if (ptable == NULL)
682 {
683 dprintf(CRITICAL, "ERROR: Partition table not found\n");
684 return;
685 }
686
687 ptn = ptable_find(ptable, "devinfo");
688 if (ptn == NULL)
689 {
690 dprintf(CRITICAL, "ERROR: No boot partition found\n");
691 return;
692 }
693
694 memcpy(info, dev, sizeof(device_info));
695
696 if (flash_write(ptn, 0, (void *)info_buf, page_size))
697 {
698 dprintf(CRITICAL, "ERROR: Cannot write device info\n");
699 return;
700 }
701}
702
703void read_device_info_flash(device_info *dev)
704{
705 struct device_info *info = (void*) info_buf;
706 struct ptentry *ptn;
707 struct ptable *ptable;
708
709 ptable = flash_get_ptable();
710 if (ptable == NULL)
711 {
712 dprintf(CRITICAL, "ERROR: Partition table not found\n");
713 return;
714 }
715
716 ptn = ptable_find(ptable, "devinfo");
717 if (ptn == NULL)
718 {
719 dprintf(CRITICAL, "ERROR: No boot partition found\n");
720 return;
721 }
722
723 if (flash_read(ptn, 0, (void *)info_buf, page_size))
724 {
725 dprintf(CRITICAL, "ERROR: Cannot write device info\n");
726 return;
727 }
728
729 if (memcmp(info->magic, DEVICE_MAGIC, DEVICE_MAGIC_SIZE))
730 {
Shashank Mittal162244e2011-08-08 19:01:25 -0700731 memcpy(info->magic, DEVICE_MAGIC, DEVICE_MAGIC_SIZE);
732 info->is_unlocked = 0;
Shashank Mittala0032282011-08-26 14:50:11 -0700733 info->is_tampered = 0;
Shashank Mittal162244e2011-08-08 19:01:25 -0700734 write_device_info_flash(info);
735 }
736 memcpy(dev, info, sizeof(device_info));
737}
738
739void write_device_info(device_info *dev)
740{
741 if(target_is_emmc_boot())
742 {
743 write_device_info_mmc(dev);
744 }
745 else
746 {
747 write_device_info_flash(dev);
748 }
749}
750
751void read_device_info(device_info *dev)
752{
753 if(target_is_emmc_boot())
754 {
755 read_device_info_mmc(dev);
756 }
757 else
758 {
759 read_device_info_flash(dev);
760 }
761}
762
763void reset_device_info()
764{
765 dprintf(ALWAYS, "reset_device_info called.");
Shashank Mittala0032282011-08-26 14:50:11 -0700766 device.is_tampered = 0;
Shashank Mittal162244e2011-08-08 19:01:25 -0700767 write_device_info(&device);
768}
769
770void set_device_root()
771{
772 dprintf(ALWAYS, "set_device_root called.");
Shashank Mittala0032282011-08-26 14:50:11 -0700773 device.is_tampered = 1;
Shashank Mittal162244e2011-08-08 19:01:25 -0700774 write_device_info(&device);
775}
776
Brian Swetland9c4c0752009-01-25 16:23:50 -0800777void cmd_boot(const char *arg, void *data, unsigned sz)
778{
779 unsigned kernel_actual;
780 unsigned ramdisk_actual;
781 static struct boot_img_hdr hdr;
782 char *ptr = ((char*) data);
783
784 if (sz < sizeof(hdr)) {
785 fastboot_fail("invalid bootimage header");
786 return;
787 }
788
789 memcpy(&hdr, data, sizeof(hdr));
790
791 /* ensure commandline is terminated */
792 hdr.cmdline[BOOT_ARGS_SIZE-1] = 0;
793
Subbaraman Narayanamurthyfbe13a02010-09-10 11:51:12 -0700794 if(target_is_emmc_boot() && hdr.page_size) {
795 page_size = hdr.page_size;
796 page_mask = page_size - 1;
797 }
798
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800799 kernel_actual = ROUND_TO_PAGE(hdr.kernel_size, page_mask);
800 ramdisk_actual = ROUND_TO_PAGE(hdr.ramdisk_size, page_mask);
Brian Swetland9c4c0752009-01-25 16:23:50 -0800801
Shashank Mittal1f0e2662011-09-01 15:06:00 -0700802 /* sz should have atleast raw boot image */
803 if (page_size + kernel_actual + ramdisk_actual > sz) {
Brian Swetland9c4c0752009-01-25 16:23:50 -0800804 fastboot_fail("incomplete bootimage");
805 return;
806 }
807
Ajay Dudanie28a6072011-07-01 13:59:46 -0700808 memmove((void*) hdr.kernel_addr, ptr + page_size, hdr.kernel_size);
809 memmove((void*) hdr.ramdisk_addr, ptr + page_size + kernel_actual, hdr.ramdisk_size);
Brian Swetland9c4c0752009-01-25 16:23:50 -0800810
811 fastboot_okay("");
812 udc_stop();
813
Amol Jadie67872e2011-06-27 14:14:11 -0700814 boot_linux((void*) hdr.kernel_addr, (void*) hdr.tags_addr,
Chandan Uddaraju885e4db2009-12-03 22:45:26 -0800815 (const char*) hdr.cmdline, board_machtype(),
Ajay Dudanie28a6072011-07-01 13:59:46 -0700816 (void*) hdr.ramdisk_addr, hdr.ramdisk_size);
Brian Swetland9c4c0752009-01-25 16:23:50 -0800817}
818
Dima Zavin214cc642009-01-26 11:16:21 -0800819void cmd_erase(const char *arg, void *data, unsigned sz)
820{
821 struct ptentry *ptn;
822 struct ptable *ptable;
823
824 ptable = flash_get_ptable();
825 if (ptable == NULL) {
826 fastboot_fail("partition table doesn't exist");
827 return;
828 }
829
830 ptn = ptable_find(ptable, arg);
831 if (ptn == NULL) {
832 fastboot_fail("unknown partition name");
833 return;
834 }
835
836 if (flash_erase(ptn)) {
837 fastboot_fail("failed to erase partition");
838 return;
839 }
840 fastboot_okay("");
841}
842
Bikas Gurungd48bd242010-09-04 19:54:32 -0700843
844void cmd_erase_mmc(const char *arg, void *data, unsigned sz)
845{
846 unsigned long long ptn = 0;
neetidb4b24d62012-01-20 12:13:09 -0800847 unsigned int out[512] = {0};
Kinson Chikf1a43512011-07-14 11:28:39 -0700848 int index = INVALID_PTN;
Bikas Gurungd48bd242010-09-04 19:54:32 -0700849
Kinson Chikf1a43512011-07-14 11:28:39 -0700850 index = partition_get_index(arg);
851 ptn = partition_get_offset(index);
Neeti Desaica8c9602011-10-06 11:40:00 -0700852
Kinson Chikf1a43512011-07-14 11:28:39 -0700853 if(ptn == 0) {
Neeti Desaica8c9602011-10-06 11:40:00 -0700854 fastboot_fail("Partition table doesn't exist\n");
Bikas Gurungd48bd242010-09-04 19:54:32 -0700855 return;
856 }
neetidb4b24d62012-01-20 12:13:09 -0800857 /* Simple inefficient version of erase. Just writing
858 0 in first block */
859 if (mmc_write(ptn , 512, (unsigned int *)out)) {
860 fastboot_fail("failed to erase partition");
Bikas Gurungd48bd242010-09-04 19:54:32 -0700861 return;
862 }
863 fastboot_okay("");
864}
865
866
Ajay Dudani5c761132011-04-07 20:19:04 -0700867void cmd_flash_mmc_img(const char *arg, void *data, unsigned sz)
Shashank Mittal23b8f422010-04-16 19:27:21 -0700868{
869 unsigned long long ptn = 0;
Subbaraman Narayanamurthyc95b5b12010-08-31 13:19:48 -0700870 unsigned long long size = 0;
Kinson Chikf1a43512011-07-14 11:28:39 -0700871 int index = INVALID_PTN;
Subbaraman Narayanamurthyc95b5b12010-08-31 13:19:48 -0700872
Greg Grisco6e754772011-06-23 12:19:39 -0700873 if (!strcmp(arg, "partition"))
874 {
875 dprintf(INFO, "Attempt to write partition image.\n");
Neeti Desai5f26aff2011-09-30 10:27:40 -0700876 if (write_partition(sz, (unsigned char *) data)) {
Greg Grisco6e754772011-06-23 12:19:39 -0700877 fastboot_fail("failed to write partition");
Shashank Mittal23b8f422010-04-16 19:27:21 -0700878 return;
879 }
880 }
Greg Grisco6e754772011-06-23 12:19:39 -0700881 else
882 {
Kinson Chikf1a43512011-07-14 11:28:39 -0700883 index = partition_get_index(arg);
884 ptn = partition_get_offset(index);
Greg Grisco6e754772011-06-23 12:19:39 -0700885 if(ptn == 0) {
886 fastboot_fail("partition table doesn't exist");
887 return;
888 }
Shashank Mittal23b8f422010-04-16 19:27:21 -0700889
Greg Grisco6e754772011-06-23 12:19:39 -0700890 if (!strcmp(arg, "boot") || !strcmp(arg, "recovery")) {
891 if (memcmp((void *)data, BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
892 fastboot_fail("image is not a boot image");
893 return;
894 }
895 }
Subbaraman Narayanamurthyc95b5b12010-08-31 13:19:48 -0700896
Kinson Chikf1a43512011-07-14 11:28:39 -0700897 size = partition_get_size(index);
Greg Grisco6e754772011-06-23 12:19:39 -0700898 if (ROUND_TO_PAGE(sz,511) > size) {
899 fastboot_fail("size too large");
900 return;
901 }
902 else if (mmc_write(ptn , sz, (unsigned int *)data)) {
903 fastboot_fail("flash write failure");
904 return;
905 }
Shashank Mittal23b8f422010-04-16 19:27:21 -0700906 }
907 fastboot_okay("");
908 return;
909}
910
Ajay Dudani5c761132011-04-07 20:19:04 -0700911void cmd_flash_mmc_sparse_img(const char *arg, void *data, unsigned sz)
912{
913 unsigned int chunk;
914 unsigned int chunk_data_sz;
915 sparse_header_t *sparse_header;
916 chunk_header_t *chunk_header;
Ajay Dudaniab18f022011-05-12 14:39:22 -0700917 uint32_t total_blocks = 0;
Ajay Dudani5c761132011-04-07 20:19:04 -0700918 unsigned long long ptn = 0;
Channagoud Kadabi65b91002011-10-11 17:34:33 +0530919 unsigned long long size = 0;
Kinson Chikf1a43512011-07-14 11:28:39 -0700920 int index = INVALID_PTN;
Ajay Dudani5c761132011-04-07 20:19:04 -0700921
Kinson Chikf1a43512011-07-14 11:28:39 -0700922 index = partition_get_index(arg);
923 ptn = partition_get_offset(index);
924 if(ptn == 0) {
Ajay Dudani5c761132011-04-07 20:19:04 -0700925 fastboot_fail("partition table doesn't exist");
926 return;
927 }
928
Channagoud Kadabi65b91002011-10-11 17:34:33 +0530929 size = partition_get_size(index);
930 if (ROUND_TO_PAGE(sz,511) > size) {
931 fastboot_fail("size too large");
932 return;
933 }
934
Ajay Dudani5c761132011-04-07 20:19:04 -0700935 /* Read and skip over sparse image header */
936 sparse_header = (sparse_header_t *) data;
937 data += sparse_header->file_hdr_sz;
938 if(sparse_header->file_hdr_sz > sizeof(sparse_header_t))
939 {
940 /* Skip the remaining bytes in a header that is longer than
941 * we expected.
942 */
943 data += (sparse_header->file_hdr_sz - sizeof(sparse_header_t));
944 }
945
Ajay Dudanib06c05f2011-05-12 14:46:10 -0700946 dprintf (SPEW, "=== Sparse Image Header ===\n");
947 dprintf (SPEW, "magic: 0x%x\n", sparse_header->magic);
948 dprintf (SPEW, "major_version: 0x%x\n", sparse_header->major_version);
949 dprintf (SPEW, "minor_version: 0x%x\n", sparse_header->minor_version);
950 dprintf (SPEW, "file_hdr_sz: %d\n", sparse_header->file_hdr_sz);
951 dprintf (SPEW, "chunk_hdr_sz: %d\n", sparse_header->chunk_hdr_sz);
952 dprintf (SPEW, "blk_sz: %d\n", sparse_header->blk_sz);
953 dprintf (SPEW, "total_blks: %d\n", sparse_header->total_blks);
954 dprintf (SPEW, "total_chunks: %d\n", sparse_header->total_chunks);
Ajay Dudani5c761132011-04-07 20:19:04 -0700955
956 /* Start processing chunks */
957 for (chunk=0; chunk<sparse_header->total_chunks; chunk++)
958 {
959 /* Read and skip over chunk header */
960 chunk_header = (chunk_header_t *) data;
961 data += sizeof(chunk_header_t);
962
963 dprintf (SPEW, "=== Chunk Header ===\n");
964 dprintf (SPEW, "chunk_type: 0x%x\n", chunk_header->chunk_type);
965 dprintf (SPEW, "chunk_data_sz: 0x%x\n", chunk_header->chunk_sz);
966 dprintf (SPEW, "total_size: 0x%x\n", chunk_header->total_sz);
967
968 if(sparse_header->chunk_hdr_sz > sizeof(chunk_header_t))
969 {
970 /* Skip the remaining bytes in a header that is longer than
971 * we expected.
972 */
973 data += (sparse_header->chunk_hdr_sz - sizeof(chunk_header_t));
974 }
975
976 chunk_data_sz = sparse_header->blk_sz * chunk_header->chunk_sz;
977 switch (chunk_header->chunk_type)
978 {
979 case CHUNK_TYPE_RAW:
980 if(chunk_header->total_sz != (sparse_header->chunk_hdr_sz +
981 chunk_data_sz))
982 {
983 fastboot_fail("Bogus chunk size for chunk type Raw");
984 return;
985 }
986
Ajay Dudaniab18f022011-05-12 14:39:22 -0700987 if(mmc_write(ptn + ((uint64_t)total_blocks*sparse_header->blk_sz),
988 chunk_data_sz,
989 (unsigned int*)data))
Ajay Dudani5c761132011-04-07 20:19:04 -0700990 {
991 fastboot_fail("flash write failure");
992 return;
993 }
994 total_blocks += chunk_header->chunk_sz;
995 data += chunk_data_sz;
996 break;
997
998 case CHUNK_TYPE_DONT_CARE:
Kinson Chik kchik@codeaurora.orgda29b1e2011-05-06 17:36:39 -0700999 total_blocks += chunk_header->chunk_sz;
1000 break;
1001
Ajay Dudani5c761132011-04-07 20:19:04 -07001002 case CHUNK_TYPE_CRC:
1003 if(chunk_header->total_sz != sparse_header->chunk_hdr_sz)
1004 {
1005 fastboot_fail("Bogus chunk size for chunk type Dont Care");
1006 return;
1007 }
1008 total_blocks += chunk_header->chunk_sz;
1009 data += chunk_data_sz;
1010 break;
1011
Kinson Chik kchik@codeaurora.orgda29b1e2011-05-06 17:36:39 -07001012 default:
Ajay Dudani5c761132011-04-07 20:19:04 -07001013 fastboot_fail("Unknown chunk type");
1014 return;
1015 }
1016 }
1017
Ajay Dudani0c6927b2011-05-18 11:12:16 -07001018 dprintf(INFO, "Wrote %d blocks, expected to write %d blocks\n",
1019 total_blocks, sparse_header->total_blks);
1020
1021 if(total_blocks != sparse_header->total_blks)
1022 {
1023 fastboot_fail("sparse image write failure");
1024 }
Ajay Dudani5c761132011-04-07 20:19:04 -07001025
1026 fastboot_okay("");
1027 return;
1028}
1029
1030void cmd_flash_mmc(const char *arg, void *data, unsigned sz)
1031{
1032 sparse_header_t *sparse_header;
kchik@codeaurora.orgbce18ea2011-04-18 20:22:28 -07001033 /* 8 Byte Magic + 2048 Byte xml + Encrypted Data */
1034 unsigned int *magic_number = (unsigned int *) data;
1035 int ret=0;
Ajay Dudani5c761132011-04-07 20:19:04 -07001036
kchik@codeaurora.orgbce18ea2011-04-18 20:22:28 -07001037 if (magic_number[0] == SSD_HEADER_MAGIC_0 &&
1038 magic_number[1] == SSD_HEADER_MAGIC_1)
1039 {
1040#ifdef SSD_ENABLE
Greg Griscod6250552011-06-29 14:40:23 -07001041 ret = decrypt_img_scm((uint32 **) &data, &sz);
kchik@codeaurora.orgbce18ea2011-04-18 20:22:28 -07001042#endif
Greg Griscod6250552011-06-29 14:40:23 -07001043 if (ret != 0) {
kchik@codeaurora.orgbce18ea2011-04-18 20:22:28 -07001044 dprintf(CRITICAL, "ERROR: Invalid secure image\n");
1045 return;
1046 }
1047 }
1048 sparse_header = (sparse_header_t *) data;
Ajay Dudani5c761132011-04-07 20:19:04 -07001049 if (sparse_header->magic != SPARSE_HEADER_MAGIC)
1050 cmd_flash_mmc_img(arg, data, sz);
1051 else
1052 cmd_flash_mmc_sparse_img(arg, data, sz);
Ajay Dudani5c761132011-04-07 20:19:04 -07001053 return;
1054}
1055
Dima Zavin214cc642009-01-26 11:16:21 -08001056void cmd_flash(const char *arg, void *data, unsigned sz)
1057{
1058 struct ptentry *ptn;
1059 struct ptable *ptable;
1060 unsigned extra = 0;
1061
1062 ptable = flash_get_ptable();
1063 if (ptable == NULL) {
1064 fastboot_fail("partition table doesn't exist");
1065 return;
1066 }
1067
1068 ptn = ptable_find(ptable, arg);
1069 if (ptn == NULL) {
1070 fastboot_fail("unknown partition name");
1071 return;
1072 }
1073
1074 if (!strcmp(ptn->name, "boot") || !strcmp(ptn->name, "recovery")) {
1075 if (memcmp((void *)data, BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
1076 fastboot_fail("image is not a boot image");
1077 return;
1078 }
1079 }
1080
Chandan Uddarajud6d45042010-02-24 21:12:45 -08001081 if (!strcmp(ptn->name, "system") || !strcmp(ptn->name, "userdata")
Channagoud Kadabi404a7062011-03-21 19:27:50 +05301082 || !strcmp(ptn->name, "persist")) {
1083 if (flash_ecc_bch_enabled())
1084 /* Spare data bytes for 8 bit ECC increased by 4 */
1085 extra = ((page_size >> 9) * 20);
1086 else
1087 extra = ((page_size >> 9) * 16);
1088 } else
Shashank Mittaldcc2e352009-11-19 19:11:16 -08001089 sz = ROUND_TO_PAGE(sz, page_mask);
Dima Zavin214cc642009-01-26 11:16:21 -08001090
1091 dprintf(INFO, "writing %d bytes to '%s'\n", sz, ptn->name);
1092 if (flash_write(ptn, extra, data, sz)) {
1093 fastboot_fail("flash write failure");
1094 return;
1095 }
1096 dprintf(INFO, "partition '%s' updated\n", ptn->name);
1097 fastboot_okay("");
1098}
1099
1100void cmd_continue(const char *arg, void *data, unsigned sz)
1101{
1102 fastboot_okay("");
1103 udc_stop();
Shashank Mittald8c42bf2010-06-09 15:44:28 -07001104 if (target_is_emmc_boot())
1105 {
1106 boot_linux_from_mmc();
1107 }
1108 else
1109 {
1110 boot_linux_from_flash();
1111 }
Dima Zavin214cc642009-01-26 11:16:21 -08001112}
1113
Chandan Uddaraju94183c02010-01-15 15:13:59 -08001114void cmd_reboot(const char *arg, void *data, unsigned sz)
1115{
Shashank Mittald8c42bf2010-06-09 15:44:28 -07001116 dprintf(INFO, "rebooting the device\n");
Chandan Uddaraju94183c02010-01-15 15:13:59 -08001117 fastboot_okay("");
1118 reboot_device(0);
1119}
1120
1121void cmd_reboot_bootloader(const char *arg, void *data, unsigned sz)
1122{
Shashank Mittald8c42bf2010-06-09 15:44:28 -07001123 dprintf(INFO, "rebooting the device\n");
Chandan Uddaraju94183c02010-01-15 15:13:59 -08001124 fastboot_okay("");
1125 reboot_device(FASTBOOT_MODE);
1126}
1127
Shashank Mittal162244e2011-08-08 19:01:25 -07001128void cmd_oem_unlock(const char *arg, void *data, unsigned sz)
1129{
1130 if(!device.is_unlocked)
1131 {
1132 device.is_unlocked = 1;
1133 write_device_info(&device);
1134 }
1135 fastboot_okay("");
1136}
1137
Shashank Mittala0032282011-08-26 14:50:11 -07001138void cmd_oem_devinfo(const char *arg, void *data, unsigned sz)
1139{
1140 char response[64];
1141 snprintf(response, 64, "\tDevice tampered: %s", (device.is_tampered ? "true" : "false"));
1142 fastboot_info(response);
1143 snprintf(response, 64, "\tDevice unlocked: %s", (device.is_unlocked ? "true" : "false"));
1144 fastboot_info(response);
1145 fastboot_okay("");
1146}
1147
Chandan Uddaraju2943fd62010-06-21 10:56:39 -07001148void splash_screen ()
1149{
1150 struct ptentry *ptn;
1151 struct ptable *ptable;
1152 struct fbcon_config *fb_display = NULL;
1153
1154 if (!target_is_emmc_boot())
1155 {
1156 ptable = flash_get_ptable();
1157 if (ptable == NULL) {
1158 dprintf(CRITICAL, "ERROR: Partition table not found\n");
Greg Griscod6250552011-06-29 14:40:23 -07001159 return;
Chandan Uddaraju2943fd62010-06-21 10:56:39 -07001160 }
1161
1162 ptn = ptable_find(ptable, "splash");
1163 if (ptn == NULL) {
1164 dprintf(CRITICAL, "ERROR: No splash partition found\n");
1165 } else {
1166 fb_display = fbcon_display();
1167 if (fb_display) {
1168 if (flash_read(ptn, 0, fb_display->base,
1169 (fb_display->width * fb_display->height * fb_display->bpp/8))) {
1170 fbcon_clear();
1171 dprintf(CRITICAL, "ERROR: Cannot read splash image\n");
1172 }
1173 }
1174 }
1175 }
1176}
1177
Brian Swetland9c4c0752009-01-25 16:23:50 -08001178void aboot_init(const struct app_descriptor *app)
1179{
Shashank Mittal4f99a882010-02-01 13:58:50 -08001180 unsigned reboot_mode = 0;
Shashank Mittald8c42bf2010-06-09 15:44:28 -07001181 unsigned usb_init = 0;
Vivek Mehta5f1c9d42011-04-01 20:11:59 -07001182 unsigned sz = 0;
Chandan Uddarajubedca152010-06-02 23:05:15 -07001183
Chandan Uddaraju2943fd62010-06-21 10:56:39 -07001184 /* Setup page size information for nand/emmc reads */
Shashank Mittald8c42bf2010-06-09 15:44:28 -07001185 if (target_is_emmc_boot())
1186 {
1187 page_size = 2048;
1188 page_mask = page_size - 1;
1189 }
1190 else
1191 {
1192 page_size = flash_page_size();
1193 page_mask = page_size - 1;
1194 }
1195
Shashank Mittal162244e2011-08-08 19:01:25 -07001196 if(target_use_signed_kernel())
1197 {
1198 read_device_info(&device);
1199
Shashank Mittal162244e2011-08-08 19:01:25 -07001200 }
1201
Greg Griscod6250552011-06-29 14:40:23 -07001202 target_serialno((unsigned char *) sn_buf);
Ajay Dudanib06c05f2011-05-12 14:46:10 -07001203 dprintf(SPEW,"serial number: %s\n",sn_buf);
Subbaraman Narayanamurthyf17b4ae2011-02-16 20:19:56 -08001204 surf_udc_device.serialno = sn_buf;
1205
Chandan Uddaraju2943fd62010-06-21 10:56:39 -07001206 /* Check if we should do something other than booting up */
Shashank Mittald8c42bf2010-06-09 15:44:28 -07001207 if (keys_get_state(KEY_HOME) != 0)
1208 boot_into_recovery = 1;
Wentao Xu153902c2010-12-20 16:20:52 -05001209 if (keys_get_state(KEY_VOLUMEUP) != 0)
1210 boot_into_recovery = 1;
Subbaraman Narayanamurthy0e445b02011-06-19 21:34:46 -07001211 if(!boot_into_recovery)
1212 {
1213 if (keys_get_state(KEY_BACK) != 0)
1214 goto fastboot;
1215 if (keys_get_state(KEY_VOLUMEDOWN) != 0)
1216 goto fastboot;
1217 }
Shashank Mittald8c42bf2010-06-09 15:44:28 -07001218
1219 #if NO_KEYPAD_DRIVER
Kinson Chik0b1c8162011-08-31 16:31:57 -07001220 if (fastboot_trigger())
Shashank Mittald8c42bf2010-06-09 15:44:28 -07001221 goto fastboot;
1222 #endif
Chandan Uddarajubedca152010-06-02 23:05:15 -07001223
Ajay Dudani77421292010-10-27 19:34:06 -07001224 reboot_mode = check_reboot_mode();
1225 if (reboot_mode == RECOVERY_MODE) {
1226 boot_into_recovery = 1;
1227 } else if(reboot_mode == FASTBOOT_MODE) {
1228 goto fastboot;
1229 }
1230
Shashank Mittal23b8f422010-04-16 19:27:21 -07001231 if (target_is_emmc_boot())
Shashank Mittald8c42bf2010-06-09 15:44:28 -07001232 {
Subbaraman Narayanamurthy0e445b02011-06-19 21:34:46 -07001233 if(emmc_recovery_init())
1234 dprintf(ALWAYS,"error in emmc_recovery_init\n");
Shashank Mittala0032282011-08-26 14:50:11 -07001235 if(target_use_signed_kernel())
1236 {
1237 if((device.is_unlocked) || (device.is_tampered))
1238 {
1239 #ifdef TZ_TAMPER_FUSE
1240 set_tamper_fuse_cmd();
1241 #endif
1242 }
1243 }
Shashank Mittald8c42bf2010-06-09 15:44:28 -07001244 boot_linux_from_mmc();
1245 }
1246 else
1247 {
Shashank Mittald8c42bf2010-06-09 15:44:28 -07001248 recovery_init();
1249 boot_linux_from_flash();
1250 }
Dima Zavinb4283602009-01-26 16:36:57 -08001251 dprintf(CRITICAL, "ERROR: Could not do normal boot. Reverting "
1252 "to fastboot mode.\n");
1253
1254fastboot:
Chandan Uddaraju2943fd62010-06-21 10:56:39 -07001255
Shashank Mittal162244e2011-08-08 19:01:25 -07001256 target_fastboot_init();
Amol Jadi57abe4c2011-05-24 15:47:27 -07001257
Shashank Mittald8c42bf2010-06-09 15:44:28 -07001258 if(!usb_init)
1259 udc_init(&surf_udc_device);
Brian Swetland9c4c0752009-01-25 16:23:50 -08001260
1261 fastboot_register("boot", cmd_boot);
Bikas Gurungd48bd242010-09-04 19:54:32 -07001262
Shashank Mittal23b8f422010-04-16 19:27:21 -07001263 if (target_is_emmc_boot())
Shashank Mittald8c42bf2010-06-09 15:44:28 -07001264 {
1265 fastboot_register("flash:", cmd_flash_mmc);
Bikas Gurungd48bd242010-09-04 19:54:32 -07001266 fastboot_register("erase:", cmd_erase_mmc);
Shashank Mittald8c42bf2010-06-09 15:44:28 -07001267 }
1268 else
1269 {
1270 fastboot_register("flash:", cmd_flash);
Bikas Gurungd48bd242010-09-04 19:54:32 -07001271 fastboot_register("erase:", cmd_erase);
Shashank Mittald8c42bf2010-06-09 15:44:28 -07001272 }
1273
1274 fastboot_register("continue", cmd_continue);
Chandan Uddaraju94183c02010-01-15 15:13:59 -08001275 fastboot_register("reboot", cmd_reboot);
1276 fastboot_register("reboot-bootloader", cmd_reboot_bootloader);
Shashank Mittal162244e2011-08-08 19:01:25 -07001277 fastboot_register("oem unlock", cmd_oem_unlock);
Shashank Mittala0032282011-08-26 14:50:11 -07001278 fastboot_register("oem device-info", cmd_oem_devinfo);
Subbaraman Narayanamurthyeb92bcc2010-07-20 14:32:46 -07001279 fastboot_publish("product", TARGET(BOARD));
Brian Swetland9c4c0752009-01-25 16:23:50 -08001280 fastboot_publish("kernel", "lk");
Trevor Bourget59b25d52012-01-13 18:43:36 -08001281 fastboot_publish("serialno", sn_buf);
Kinson Chikf1a43512011-07-14 11:28:39 -07001282 partition_dump();
Vivek Mehta5f1c9d42011-04-01 20:11:59 -07001283 sz = target_get_max_flash_size();
1284 fastboot_init(target_get_scratch_address(), sz);
Brian Swetland9c4c0752009-01-25 16:23:50 -08001285 udc_start();
Brian Swetland9c4c0752009-01-25 16:23:50 -08001286}
1287
1288APP_START(aboot)
1289 .init = aboot_init,
1290APP_END
1291