blob: f81a44b5ab7488b4c789759d9a511c6331fd6d23 [file] [log] [blame]
Brian Swetland9c4c0752009-01-25 16:23:50 -08001/*
2 * Copyright (c) 2009, Google Inc.
3 * All rights reserved.
4 *
Neeti Desaie245d492012-06-01 12:52:13 -07005 * Copyright (c) 2009-2012, 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
Neeti Desai17379b82012-06-04 18:42:53 -070052#if DEVICE_TREE
53#include <libfdt.h>
54#endif
55
Shashank Mittalcd98d472011-08-02 14:29:24 -070056#include "image_verify.h"
Shashank Mittal024c0332010-02-03 11:44:00 -080057#include "recovery.h"
Brian Swetland9c4c0752009-01-25 16:23:50 -080058#include "bootimg.h"
59#include "fastboot.h"
Ajay Dudani5c761132011-04-07 20:19:04 -070060#include "sparse_format.h"
Greg Grisco6e754772011-06-23 12:19:39 -070061#include "mmc.h"
Shashank Mittal162244e2011-08-08 19:01:25 -070062#include "devinfo.h"
Brian Swetland9c4c0752009-01-25 16:23:50 -080063
Shashank Mittal162244e2011-08-08 19:01:25 -070064#include "scm.h"
kchik@codeaurora.orgbce18ea2011-04-18 20:22:28 -070065
Subbaraman Narayanamurthyeb92bcc2010-07-20 14:32:46 -070066#define EXPAND(NAME) #NAME
67#define TARGET(NAME) EXPAND(NAME)
Chandan Uddarajuda919832009-11-17 01:06:11 -080068#define DEFAULT_CMDLINE "mem=100M console=null";
Brian Swetland2defe162009-08-18 14:35:59 -070069
Ajay Dudanicd01f9b2010-02-23 21:13:04 -080070#ifdef MEMBASE
71#define EMMC_BOOT_IMG_HEADER_ADDR (0xFF000+(MEMBASE))
72#else
David Ng183a7422009-12-07 14:55:21 -080073#define EMMC_BOOT_IMG_HEADER_ADDR 0xFF000
Ajay Dudanicd01f9b2010-02-23 21:13:04 -080074#endif
75
Chandan Uddarajude85d3f2010-01-05 16:32:33 -080076#define RECOVERY_MODE 0x77665502
77#define FASTBOOT_MODE 0x77665500
78
Neeti Desai17379b82012-06-04 18:42:53 -070079#if DEVICE_TREE
80int update_device_tree(const void *, char *, void *, unsigned);
81#endif
82
David Ng183a7422009-12-07 14:55:21 -080083static const char *emmc_cmdline = " androidboot.emmc=true";
Subbaraman Narayanamurthyf17b4ae2011-02-16 20:19:56 -080084static const char *usb_sn_cmdline = " androidboot.serialno=";
Ajay Dudanica3a33c2011-11-18 08:31:40 -080085static const char *battchg_pause = " androidboot.mode=charger";
Shashank Mittalcd98d472011-08-02 14:29:24 -070086static const char *auth_kernel = " androidboot.authorized_kernel=true";
David Ng183a7422009-12-07 14:55:21 -080087
Ajay Dudani6cff85e2011-02-04 16:02:16 -080088static const char *baseband_apq = " androidboot.baseband=apq";
89static const char *baseband_msm = " androidboot.baseband=msm";
90static const char *baseband_csfb = " androidboot.baseband=csfb";
91static const char *baseband_svlte2a = " androidboot.baseband=svlte2a";
Ajay Dudani403bc492011-09-30 16:17:21 -070092static const char *baseband_mdm = " androidboot.baseband=mdm";
Amol Jadi5c61a952012-05-04 17:05:35 -070093static const char *baseband_sglte = " androidboot.baseband=sglte";
Ajay Dudanid04110c2011-01-17 23:55:07 -080094
Shashank Mittalcd98d472011-08-02 14:29:24 -070095/* Assuming unauthorized kernel image by default */
96static int auth_kernel_img = 0;
97
Shashank Mittal162244e2011-08-08 19:01:25 -070098static device_info device = {DEVICE_MAGIC, 0, 0};
99
Brian Swetland9c4c0752009-01-25 16:23:50 -0800100static struct udc_device surf_udc_device = {
101 .vendor_id = 0x18d1,
Chandan Uddarajuc53a1a12009-11-18 14:53:40 -0800102 .product_id = 0xD00D,
Brian Swetland9c4c0752009-01-25 16:23:50 -0800103 .version_id = 0x0100,
104 .manufacturer = "Google",
105 .product = "Android",
106};
107
Dima Zavin42168f22009-01-30 11:52:22 -0800108struct atag_ptbl_entry
109{
110 char name[16];
111 unsigned offset;
112 unsigned size;
113 unsigned flags;
114};
115
Subbaraman Narayanamurthyf17b4ae2011-02-16 20:19:56 -0800116char sn_buf[13];
Greg Griscod6250552011-06-29 14:40:23 -0700117
Greg Griscod2471ef2011-07-14 13:00:42 -0700118extern int emmc_recovery_init(void);
119
Kinson Chik0b1c8162011-08-31 16:31:57 -0700120#if NO_KEYPAD_DRIVER
121extern int fastboot_trigger(void);
122#endif
Greg Griscod2471ef2011-07-14 13:00:42 -0700123
Dima Zavin42168f22009-01-30 11:52:22 -0800124static void ptentry_to_tag(unsigned **ptr, struct ptentry *ptn)
125{
126 struct atag_ptbl_entry atag_ptn;
127
128 memcpy(atag_ptn.name, ptn->name, 16);
129 atag_ptn.name[15] = '\0';
130 atag_ptn.offset = ptn->start;
131 atag_ptn.size = ptn->length;
132 atag_ptn.flags = ptn->flags;
133 memcpy(*ptr, &atag_ptn, sizeof(struct atag_ptbl_entry));
134 *ptr += sizeof(struct atag_ptbl_entry) / sizeof(unsigned);
135}
Brian Swetland9c4c0752009-01-25 16:23:50 -0800136
Neeti Desaie245d492012-06-01 12:52:13 -0700137unsigned char *update_cmdline(const char * cmdline)
Brian Swetland9c4c0752009-01-25 16:23:50 -0800138{
David Ng183a7422009-12-07 14:55:21 -0800139 int cmdline_len = 0;
140 int have_cmdline = 0;
Amol Jadi168b7712012-03-06 16:15:00 -0800141 unsigned char *cmdline_final = NULL;
Neeti Desaie245d492012-06-01 12:52:13 -0700142 int pause_at_bootup = 0;
Dima Zavin42168f22009-01-30 11:52:22 -0800143
Brian Swetland9c4c0752009-01-25 16:23:50 -0800144 if (cmdline && cmdline[0]) {
David Ng183a7422009-12-07 14:55:21 -0800145 cmdline_len = strlen(cmdline);
146 have_cmdline = 1;
147 }
148 if (target_is_emmc_boot()) {
149 cmdline_len += strlen(emmc_cmdline);
150 }
Subbaraman Narayanamurthyf17b4ae2011-02-16 20:19:56 -0800151
152 cmdline_len += strlen(usb_sn_cmdline);
153 cmdline_len += strlen(sn_buf);
154
David Ngf773dde2010-07-26 19:55:08 -0700155 if (target_pause_for_battery_charge()) {
156 pause_at_bootup = 1;
157 cmdline_len += strlen(battchg_pause);
158 }
Ajay Dudanid04110c2011-01-17 23:55:07 -0800159
Shashank Mittalcd98d472011-08-02 14:29:24 -0700160 if(target_use_signed_kernel() && auth_kernel_img) {
161 cmdline_len += strlen(auth_kernel);
162 }
163
Ajay Dudanid04110c2011-01-17 23:55:07 -0800164 /* Determine correct androidboot.baseband to use */
165 switch(target_baseband())
166 {
167 case BASEBAND_APQ:
168 cmdline_len += strlen(baseband_apq);
169 break;
170
171 case BASEBAND_MSM:
172 cmdline_len += strlen(baseband_msm);
173 break;
174
175 case BASEBAND_CSFB:
176 cmdline_len += strlen(baseband_csfb);
177 break;
178
Ajay Dudani6cff85e2011-02-04 16:02:16 -0800179 case BASEBAND_SVLTE2A:
180 cmdline_len += strlen(baseband_svlte2a);
Ajay Dudanid04110c2011-01-17 23:55:07 -0800181 break;
Ajay Dudani403bc492011-09-30 16:17:21 -0700182
183 case BASEBAND_MDM:
184 cmdline_len += strlen(baseband_mdm);
185 break;
Amol Jadi5c61a952012-05-04 17:05:35 -0700186
187 case BASEBAND_SGLTE:
188 cmdline_len += strlen(baseband_sglte);
189 break;
Ajay Dudanid04110c2011-01-17 23:55:07 -0800190 }
191
David Ng183a7422009-12-07 14:55:21 -0800192 if (cmdline_len > 0) {
193 const char *src;
Neeti Desaie245d492012-06-01 12:52:13 -0700194 char *dst = malloc((cmdline_len + 4) & (~3));
195 assert(dst != NULL);
196
Amol Jadi168b7712012-03-06 16:15:00 -0800197 /* Save start ptr for debug print */
Neeti Desaie245d492012-06-01 12:52:13 -0700198 cmdline_final = dst;
David Ng183a7422009-12-07 14:55:21 -0800199 if (have_cmdline) {
200 src = cmdline;
201 while ((*dst++ = *src++));
202 }
203 if (target_is_emmc_boot()) {
204 src = emmc_cmdline;
205 if (have_cmdline) --dst;
David Ngf773dde2010-07-26 19:55:08 -0700206 have_cmdline = 1;
207 while ((*dst++ = *src++));
208 }
Subbaraman Narayanamurthyf17b4ae2011-02-16 20:19:56 -0800209
210 src = usb_sn_cmdline;
211 if (have_cmdline) --dst;
212 have_cmdline = 1;
213 while ((*dst++ = *src++));
214 src = sn_buf;
215 if (have_cmdline) --dst;
216 have_cmdline = 1;
217 while ((*dst++ = *src++));
218
David Ngf773dde2010-07-26 19:55:08 -0700219 if (pause_at_bootup) {
220 src = battchg_pause;
221 if (have_cmdline) --dst;
David Ng183a7422009-12-07 14:55:21 -0800222 while ((*dst++ = *src++));
223 }
Ajay Dudanid04110c2011-01-17 23:55:07 -0800224
Shashank Mittalcd98d472011-08-02 14:29:24 -0700225 if(target_use_signed_kernel() && auth_kernel_img) {
226 src = auth_kernel;
227 if (have_cmdline) --dst;
228 while ((*dst++ = *src++));
229 }
230
Ajay Dudanid04110c2011-01-17 23:55:07 -0800231 switch(target_baseband())
232 {
233 case BASEBAND_APQ:
234 src = baseband_apq;
235 if (have_cmdline) --dst;
236 while ((*dst++ = *src++));
237 break;
238
239 case BASEBAND_MSM:
240 src = baseband_msm;
241 if (have_cmdline) --dst;
242 while ((*dst++ = *src++));
243 break;
244
245 case BASEBAND_CSFB:
246 src = baseband_csfb;
247 if (have_cmdline) --dst;
248 while ((*dst++ = *src++));
249 break;
250
Ajay Dudani6cff85e2011-02-04 16:02:16 -0800251 case BASEBAND_SVLTE2A:
252 src = baseband_svlte2a;
Ajay Dudanid04110c2011-01-17 23:55:07 -0800253 if (have_cmdline) --dst;
254 while ((*dst++ = *src++));
255 break;
Ajay Dudani403bc492011-09-30 16:17:21 -0700256
257 case BASEBAND_MDM:
258 src = baseband_mdm;
259 if (have_cmdline) --dst;
260 while ((*dst++ = *src++));
261 break;
Amol Jadi5c61a952012-05-04 17:05:35 -0700262
263 case BASEBAND_SGLTE:
264 src = baseband_sglte;
265 if (have_cmdline) --dst;
266 while ((*dst++ = *src++));
267 break;
Ajay Dudanid04110c2011-01-17 23:55:07 -0800268 }
Neeti Desaie245d492012-06-01 12:52:13 -0700269 }
270 return cmdline_final;
271}
272
273unsigned *atag_core(unsigned *ptr)
274{
275 /* CORE */
276 *ptr++ = 2;
277 *ptr++ = 0x54410001;
278
279 return ptr;
280
281}
282
283unsigned *atag_ramdisk(unsigned *ptr, void *ramdisk,
284 unsigned ramdisk_size)
285{
286 if (ramdisk_size) {
287 *ptr++ = 4;
288 *ptr++ = 0x54420005;
289 *ptr++ = (unsigned)ramdisk;
290 *ptr++ = ramdisk_size;
Brian Swetland9c4c0752009-01-25 16:23:50 -0800291 }
292
Neeti Desaie245d492012-06-01 12:52:13 -0700293 return ptr;
294}
295
296unsigned *atag_ptable(unsigned **ptr_addr)
297{
298 int i;
299 struct ptable *ptable;
300
301 if ((ptable = flash_get_ptable()) && (ptable->count != 0)) {
302 *(*ptr_addr)++ = 2 + (ptable->count * (sizeof(struct atag_ptbl_entry) /
303 sizeof(unsigned)));
304 *(*ptr_addr)++ = 0x4d534d70;
305 for (i = 0; i < ptable->count; ++i)
306 ptentry_to_tag(ptr_addr, ptable_get(ptable, i));
307 }
308
309 return (*ptr_addr);
310}
311
312unsigned *atag_cmdline(unsigned *ptr, const char *cmdline)
313{
314 int cmdline_length = 0;
315 int n;
316 unsigned char *cmdline_final = NULL;
317 char *dest;
318
319 cmdline_final = update_cmdline(cmdline);
320 if (cmdline_final){
321 dprintf(INFO, "cmdline: %s\n", cmdline_final);
322 }
323
324 cmdline_length =strlen(cmdline_final);
325 n = (cmdline_length + 4) & (~3);
326
327 *ptr++ = (n / 4) + 2;
328 *ptr++ = 0x54410009;
329 dest = (char *) ptr;
330 while (*dest++ = *cmdline_final++);
331 ptr += (n / 4);
332
333 return ptr;
334}
335
336unsigned *atag_end(unsigned *ptr)
337{
Brian Swetland9c4c0752009-01-25 16:23:50 -0800338 /* END */
339 *ptr++ = 0;
340 *ptr++ = 0;
341
Neeti Desaie245d492012-06-01 12:52:13 -0700342 return ptr;
343}
344
345void generate_atags(unsigned *ptr, const char *cmdline,
346 void *ramdisk, unsigned ramdisk_size)
347{
348
349 ptr = atag_core(ptr);
350 ptr = atag_ramdisk(ptr, ramdisk, ramdisk_size);
351 ptr = target_atag_mem(ptr);
352
353 /* Skip NAND partition ATAGS for eMMC boot */
354 if (!target_is_emmc_boot()){
355 ptr = atag_ptable(&ptr);
356 }
357
358 ptr = atag_cmdline(ptr, cmdline);
359 ptr = atag_end(ptr);
360}
361
362void boot_linux(void *kernel, unsigned *tags,
363 const char *cmdline, unsigned machtype,
364 void *ramdisk, unsigned ramdisk_size)
365{
Neeti Desai17379b82012-06-04 18:42:53 -0700366 int ret = 0;
Neeti Desaie245d492012-06-01 12:52:13 -0700367 void (*entry)(unsigned, unsigned, unsigned*) = kernel;
368
Neeti Desai17379b82012-06-04 18:42:53 -0700369#if DEVICE_TREE
370 /* Update the Device Tree */
371 ret = update_device_tree(tags, cmdline, ramdisk, ramdisk_size);
372 if(ret)
373 {
374 dprintf(CRITICAL, "ERROR: Updating Device Tree Failed \n");
375 ASSERT(0);
376 }
377#else
Neeti Desaie245d492012-06-01 12:52:13 -0700378 /* Generating the Atags */
379 generate_atags(tags, cmdline, ramdisk, ramdisk_size);
Neeti Desai17379b82012-06-04 18:42:53 -0700380#endif
Neeti Desaie245d492012-06-01 12:52:13 -0700381
Brian Swetland9c4c0752009-01-25 16:23:50 -0800382 dprintf(INFO, "booting linux @ %p, ramdisk @ %p (%d)\n",
383 kernel, ramdisk, ramdisk_size);
Brian Swetland9c4c0752009-01-25 16:23:50 -0800384
385 enter_critical_section();
Amol Jadi4421e652011-06-16 15:00:48 -0700386 /* do any platform specific cleanup before kernel entry */
387 platform_uninit();
Brian Swetland9c4c0752009-01-25 16:23:50 -0800388 arch_disable_cache(UCACHE);
Amol Jadi01c2c702012-07-19 23:03:45 -0700389 /* NOTE:
390 * The value of "entry" is getting corrupted at this point.
391 * The value is in R4 and gets pushed to stack on entry into
392 * disable_cache(), however, on return it is not the same.
393 * Not entirely sure why this dsb() seems to take of this.
394 * The stack pop operation on return from disable_cache()
395 * should restore R4 properly, but that is not happening.
396 * Will need to revisit to find the root cause.
397 */
398 dsb();
Brian Swetland9c4c0752009-01-25 16:23:50 -0800399 arch_disable_mmu();
Brian Swetland9c4c0752009-01-25 16:23:50 -0800400 entry(0, machtype, tags);
Brian Swetland9c4c0752009-01-25 16:23:50 -0800401}
402
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800403unsigned page_size = 0;
404unsigned page_mask = 0;
Brian Swetland9c4c0752009-01-25 16:23:50 -0800405
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800406#define ROUND_TO_PAGE(x,y) (((x) + (y)) & (~(y)))
Brian Swetland9c4c0752009-01-25 16:23:50 -0800407
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800408static unsigned char buf[4096]; //Equal to max-supported pagesize
Dima Zavin214cc642009-01-26 11:16:21 -0800409
Shashank Mittal23b8f422010-04-16 19:27:21 -0700410int boot_linux_from_mmc(void)
411{
412 struct boot_img_hdr *hdr = (void*) buf;
413 struct boot_img_hdr *uhdr;
414 unsigned offset = 0;
415 unsigned long long ptn = 0;
416 unsigned n = 0;
417 const char *cmdline;
Kinson Chikf1a43512011-07-14 11:28:39 -0700418 int index = INVALID_PTN;
Shashank Mittal23b8f422010-04-16 19:27:21 -0700419
Shashank Mittalcd98d472011-08-02 14:29:24 -0700420 unsigned char *image_addr = 0;
421 unsigned kernel_actual;
422 unsigned ramdisk_actual;
423 unsigned imagesize_actual;
424
Shashank Mittal23b8f422010-04-16 19:27:21 -0700425 uhdr = (struct boot_img_hdr *)EMMC_BOOT_IMG_HEADER_ADDR;
426 if (!memcmp(uhdr->magic, BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
427 dprintf(INFO, "Unified boot method!\n");
428 hdr = uhdr;
429 goto unified_boot;
430 }
Greg Griscod6250552011-06-29 14:40:23 -0700431 if (!boot_into_recovery) {
Kinson Chikf1a43512011-07-14 11:28:39 -0700432 index = partition_get_index("boot");
433 ptn = partition_get_offset(index);
434 if(ptn == 0) {
Shashank Mittal85b91f62010-10-30 10:12:38 -0700435 dprintf(CRITICAL, "ERROR: No boot partition found\n");
436 return -1;
437 }
Kinson Chikf1a43512011-07-14 11:28:39 -0700438 }
439 else {
440 index = partition_get_index("recovery");
441 ptn = partition_get_offset(index);
442 if(ptn == 0) {
Shashank Mittal85b91f62010-10-30 10:12:38 -0700443 dprintf(CRITICAL, "ERROR: No recovery partition found\n");
444 return -1;
445 }
Shashank Mittal23b8f422010-04-16 19:27:21 -0700446 }
447
Greg Griscod6250552011-06-29 14:40:23 -0700448 if (mmc_read(ptn + offset, (unsigned int *) buf, page_size)) {
Shashank Mittal23b8f422010-04-16 19:27:21 -0700449 dprintf(CRITICAL, "ERROR: Cannot read boot image header\n");
450 return -1;
451 }
Shashank Mittal23b8f422010-04-16 19:27:21 -0700452
453 if (memcmp(hdr->magic, BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
Kinson Chik kchik@codeaurora.org82e4ae62011-04-12 17:42:07 -0700454 dprintf(CRITICAL, "ERROR: Invalid boot image header\n");
Shashank Mittal23b8f422010-04-16 19:27:21 -0700455 return -1;
456 }
457
Subbaraman Narayanamurthyfbe13a02010-09-10 11:51:12 -0700458 if (hdr->page_size && (hdr->page_size != page_size)) {
459 page_size = hdr->page_size;
460 page_mask = page_size - 1;
Shashank Mittal23b8f422010-04-16 19:27:21 -0700461 }
462
Shashank Mittalcd98d472011-08-02 14:29:24 -0700463 /* Authenticate Kernel */
Shashank Mittala0032282011-08-26 14:50:11 -0700464 if(target_use_signed_kernel() && (!device.is_unlocked) && (!device.is_tampered))
Subbaraman Narayanamurthy958fa242011-01-27 17:42:38 -0800465 {
Shashank Mittalcd98d472011-08-02 14:29:24 -0700466 image_addr = (unsigned char *)target_get_scratch_address();
467 kernel_actual = ROUND_TO_PAGE(hdr->kernel_size, page_mask);
468 ramdisk_actual = ROUND_TO_PAGE(hdr->ramdisk_size, page_mask);
469 imagesize_actual = (page_size + kernel_actual + ramdisk_actual);
470
471 offset = 0;
Shashank Mittal162244e2011-08-08 19:01:25 -0700472
473 /* Assuming device rooted at this time */
Shashank Mittala0032282011-08-26 14:50:11 -0700474 device.is_tampered = 1;
Shashank Mittal162244e2011-08-08 19:01:25 -0700475
Shashank Mittalcd98d472011-08-02 14:29:24 -0700476 /* Read image without signature */
477 if (mmc_read(ptn + offset, (void *)image_addr, imagesize_actual))
478 {
479 dprintf(CRITICAL, "ERROR: Cannot read boot image\n");
480 return -1;
Subbaraman Narayanamurthy958fa242011-01-27 17:42:38 -0800481 }
Shashank Mittalcd98d472011-08-02 14:29:24 -0700482
483 offset = imagesize_actual;
484 /* Read signature */
485 if(mmc_read(ptn + offset, (void *)(image_addr + offset), page_size))
486 {
487 dprintf(CRITICAL, "ERROR: Cannot read boot image signature\n");
488 }
489 else
490 {
491 auth_kernel_img = image_verify((unsigned char *)image_addr,
492 (unsigned char *)(image_addr + imagesize_actual),
493 imagesize_actual,
494 CRYPTO_AUTH_ALG_SHA256);
Shashank Mittal162244e2011-08-08 19:01:25 -0700495
496 if(auth_kernel_img)
497 {
498 /* Authorized kernel */
Shashank Mittala0032282011-08-26 14:50:11 -0700499 device.is_tampered = 0;
Shashank Mittal162244e2011-08-08 19:01:25 -0700500 }
Shashank Mittalcd98d472011-08-02 14:29:24 -0700501 }
502
503 /* Move kernel and ramdisk to correct address */
504 memmove((void*) hdr->kernel_addr, (char *)(image_addr + page_size), hdr->kernel_size);
505 memmove((void*) hdr->ramdisk_addr, (char *)(image_addr + page_size + kernel_actual), hdr->ramdisk_size);
Shashank Mittal162244e2011-08-08 19:01:25 -0700506
507 /* Make sure everything from scratch address is read before next step!*/
Shashank Mittala0032282011-08-26 14:50:11 -0700508 if(device.is_tampered)
Shashank Mittal162244e2011-08-08 19:01:25 -0700509 {
510 write_device_info_mmc(&device);
511 #ifdef TZ_TAMPER_FUSE
512 set_tamper_fuse_cmd();
513 #endif
514 }
Channagoud Kadabibf695c62012-04-10 13:31:56 +0530515 #if USE_PCOM_SECBOOT
516 set_tamper_flag(device.is_tampered);
517 #endif
Shashank Mittal23b8f422010-04-16 19:27:21 -0700518 }
Shashank Mittalcd98d472011-08-02 14:29:24 -0700519 else
520 {
521 offset += page_size;
522
523 n = ROUND_TO_PAGE(hdr->kernel_size, page_mask);
524 if (mmc_read(ptn + offset, (void *)hdr->kernel_addr, n)) {
525 dprintf(CRITICAL, "ERROR: Cannot read kernel image\n");
526 return -1;
527 }
528 offset += n;
529
530 n = ROUND_TO_PAGE(hdr->ramdisk_size, page_mask);
531 if(n != 0)
532 {
533 if (mmc_read(ptn + offset, (void *)hdr->ramdisk_addr, n)) {
534 dprintf(CRITICAL, "ERROR: Cannot read ramdisk image\n");
535 return -1;
536 }
537 }
538 offset += n;
539 }
Shashank Mittal23b8f422010-04-16 19:27:21 -0700540
541unified_boot:
542 dprintf(INFO, "\nkernel @ %x (%d bytes)\n", hdr->kernel_addr,
543 hdr->kernel_size);
544 dprintf(INFO, "ramdisk @ %x (%d bytes)\n", hdr->ramdisk_addr,
545 hdr->ramdisk_size);
546
547 if(hdr->cmdline[0]) {
548 cmdline = (char*) hdr->cmdline;
549 } else {
550 cmdline = DEFAULT_CMDLINE;
551 }
552 dprintf(INFO, "cmdline = '%s'\n", cmdline);
553
554 dprintf(INFO, "\nBooting Linux\n");
Greg Griscod2471ef2011-07-14 13:00:42 -0700555 boot_linux((void *)hdr->kernel_addr, (unsigned *) hdr->tags_addr,
Shashank Mittal23b8f422010-04-16 19:27:21 -0700556 (const char *)cmdline, board_machtype(),
557 (void *)hdr->ramdisk_addr, hdr->ramdisk_size);
558
559 return 0;
560}
561
Dima Zavin214cc642009-01-26 11:16:21 -0800562int boot_linux_from_flash(void)
563{
564 struct boot_img_hdr *hdr = (void*) buf;
565 unsigned n;
566 struct ptentry *ptn;
567 struct ptable *ptable;
568 unsigned offset = 0;
569 const char *cmdline;
Chandan Uddarajude85d3f2010-01-05 16:32:33 -0800570
Shashank Mittalcd98d472011-08-02 14:29:24 -0700571 unsigned char *image_addr = 0;
572 unsigned kernel_actual;
573 unsigned ramdisk_actual;
574 unsigned imagesize_actual;
575
David Ng183a7422009-12-07 14:55:21 -0800576 if (target_is_emmc_boot()) {
577 hdr = (struct boot_img_hdr *)EMMC_BOOT_IMG_HEADER_ADDR;
578 if (memcmp(hdr->magic, BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
579 dprintf(CRITICAL, "ERROR: Invalid boot image header\n");
580 return -1;
581 }
582 goto continue_boot;
583 }
584
Dima Zavin214cc642009-01-26 11:16:21 -0800585 ptable = flash_get_ptable();
586 if (ptable == NULL) {
587 dprintf(CRITICAL, "ERROR: Partition table not found\n");
588 return -1;
589 }
590
Chandan Uddarajude85d3f2010-01-05 16:32:33 -0800591 if(!boot_into_recovery)
592 {
593 ptn = ptable_find(ptable, "boot");
594 if (ptn == NULL) {
595 dprintf(CRITICAL, "ERROR: No boot partition found\n");
596 return -1;
597 }
598 }
599 else
600 {
601 ptn = ptable_find(ptable, "recovery");
602 if (ptn == NULL) {
603 dprintf(CRITICAL, "ERROR: No recovery partition found\n");
604 return -1;
605 }
Dima Zavin214cc642009-01-26 11:16:21 -0800606 }
607
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800608 if (flash_read(ptn, offset, buf, page_size)) {
Dima Zavin214cc642009-01-26 11:16:21 -0800609 dprintf(CRITICAL, "ERROR: Cannot read boot image header\n");
610 return -1;
611 }
Dima Zavin214cc642009-01-26 11:16:21 -0800612
613 if (memcmp(hdr->magic, BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
Kinson Chik kchik@codeaurora.org82e4ae62011-04-12 17:42:07 -0700614 dprintf(CRITICAL, "ERROR: Invalid boot image header\n");
Dima Zavin214cc642009-01-26 11:16:21 -0800615 return -1;
616 }
617
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800618 if (hdr->page_size != page_size) {
Kinson Chik kchik@codeaurora.org82e4ae62011-04-12 17:42:07 -0700619 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 -0800620 return -1;
621 }
622
Shashank Mittalcd98d472011-08-02 14:29:24 -0700623 /* Authenticate Kernel */
Shashank Mittala0032282011-08-26 14:50:11 -0700624 if(target_use_signed_kernel() && (!device.is_unlocked) && (!device.is_tampered))
Shashank Mittalcd98d472011-08-02 14:29:24 -0700625 {
626 image_addr = (unsigned char *)target_get_scratch_address();
627 kernel_actual = ROUND_TO_PAGE(hdr->kernel_size, page_mask);
628 ramdisk_actual = ROUND_TO_PAGE(hdr->ramdisk_size, page_mask);
629 imagesize_actual = (page_size + kernel_actual + ramdisk_actual);
Dima Zavin214cc642009-01-26 11:16:21 -0800630
Shashank Mittalcd98d472011-08-02 14:29:24 -0700631 offset = 0;
Shashank Mittal162244e2011-08-08 19:01:25 -0700632
633 /* Assuming device rooted at this time */
Shashank Mittala0032282011-08-26 14:50:11 -0700634 device.is_tampered = 1;
Shashank Mittal162244e2011-08-08 19:01:25 -0700635
Shashank Mittalcd98d472011-08-02 14:29:24 -0700636 /* Read image without signature */
637 if (flash_read(ptn, offset, (void *)image_addr, imagesize_actual))
638 {
639 dprintf(CRITICAL, "ERROR: Cannot read boot image\n");
640 return -1;
641 }
Dima Zavin214cc642009-01-26 11:16:21 -0800642
Shashank Mittalcd98d472011-08-02 14:29:24 -0700643 offset = imagesize_actual;
644 /* Read signature */
645 if (flash_read(ptn, offset, (void *)(image_addr + offset), page_size))
646 {
647 dprintf(CRITICAL, "ERROR: Cannot read boot image signature\n");
648 }
649 else
650 {
651
652 /* Verify signature */
653 auth_kernel_img = image_verify((unsigned char *)image_addr,
654 (unsigned char *)(image_addr + imagesize_actual),
655 imagesize_actual,
656 CRYPTO_AUTH_ALG_SHA256);
Shashank Mittal162244e2011-08-08 19:01:25 -0700657
658 if(auth_kernel_img)
659 {
660 /* Authorized kernel */
Shashank Mittala0032282011-08-26 14:50:11 -0700661 device.is_tampered = 0;
Shashank Mittal162244e2011-08-08 19:01:25 -0700662 }
Shashank Mittalcd98d472011-08-02 14:29:24 -0700663 }
664
665 /* Move kernel and ramdisk to correct address */
666 memmove((void*) hdr->kernel_addr, (char *)(image_addr + page_size), hdr->kernel_size);
667 memmove((void*) hdr->ramdisk_addr, (char *)(image_addr + page_size + kernel_actual), hdr->ramdisk_size);
Shashank Mittal162244e2011-08-08 19:01:25 -0700668
669 /* Make sure everything from scratch address is read before next step!*/
Shashank Mittala0032282011-08-26 14:50:11 -0700670 if(device.is_tampered)
Shashank Mittal162244e2011-08-08 19:01:25 -0700671 {
672 write_device_info_flash(&device);
673 }
Channagoud Kadabi5c86fe32012-02-16 10:58:48 +0530674#if USE_PCOM_SECBOOT
675 set_tamper_flag(device.is_tampered);
676#endif
Shashank Mittalcd98d472011-08-02 14:29:24 -0700677 }
678 else
679 {
Shashank Mittal162244e2011-08-08 19:01:25 -0700680 offset = page_size;
681
Shashank Mittalcd98d472011-08-02 14:29:24 -0700682 n = ROUND_TO_PAGE(hdr->kernel_size, page_mask);
683 if (flash_read(ptn, offset, (void *)hdr->kernel_addr, n)) {
684 dprintf(CRITICAL, "ERROR: Cannot read kernel image\n");
685 return -1;
686 }
687 offset += n;
688
689 n = ROUND_TO_PAGE(hdr->ramdisk_size, page_mask);
690 if (flash_read(ptn, offset, (void *)hdr->ramdisk_addr, n)) {
691 dprintf(CRITICAL, "ERROR: Cannot read ramdisk image\n");
692 return -1;
693 }
694 offset += n;
695 }
David Ng183a7422009-12-07 14:55:21 -0800696continue_boot:
Dima Zavin214cc642009-01-26 11:16:21 -0800697 dprintf(INFO, "\nkernel @ %x (%d bytes)\n", hdr->kernel_addr,
698 hdr->kernel_size);
699 dprintf(INFO, "ramdisk @ %x (%d bytes)\n", hdr->ramdisk_addr,
700 hdr->ramdisk_size);
701
702 if(hdr->cmdline[0]) {
703 cmdline = (char*) hdr->cmdline;
704 } else {
705 cmdline = DEFAULT_CMDLINE;
706 }
707 dprintf(INFO, "cmdline = '%s'\n", cmdline);
708
709 /* TODO: create/pass atags to kernel */
710
711 dprintf(INFO, "\nBooting Linux\n");
Ajay Dudanie28a6072011-07-01 13:59:46 -0700712 boot_linux((void *)hdr->kernel_addr, (void *)hdr->tags_addr,
Chandan Uddaraju885e4db2009-12-03 22:45:26 -0800713 (const char *)cmdline, board_machtype(),
Dima Zavin214cc642009-01-26 11:16:21 -0800714 (void *)hdr->ramdisk_addr, hdr->ramdisk_size);
715
716 return 0;
717}
Brian Swetland9c4c0752009-01-25 16:23:50 -0800718
Shashank Mittal162244e2011-08-08 19:01:25 -0700719unsigned char info_buf[4096];
720void write_device_info_mmc(device_info *dev)
721{
722 struct device_info *info = (void*) info_buf;
723 unsigned long long ptn = 0;
724 unsigned long long size;
725 int index = INVALID_PTN;
726
727 index = partition_get_index("aboot");
728 ptn = partition_get_offset(index);
729 if(ptn == 0)
730 {
731 return;
732 }
733
734 size = partition_get_size(index);
735
736 memcpy(info, dev, sizeof(device_info));
737
738 if(mmc_write((ptn + size - 512), 512, (void *)info_buf))
739 {
740 dprintf(CRITICAL, "ERROR: Cannot write device info\n");
741 return;
742 }
743}
744
745void read_device_info_mmc(device_info *dev)
746{
747 struct device_info *info = (void*) info_buf;
748 unsigned long long ptn = 0;
749 unsigned long long size;
750 int index = INVALID_PTN;
751
752 index = partition_get_index("aboot");
753 ptn = partition_get_offset(index);
754 if(ptn == 0)
755 {
756 return;
757 }
758
759 size = partition_get_size(index);
760
761 if(mmc_read((ptn + size - 512), (void *)info_buf, 512))
762 {
763 dprintf(CRITICAL, "ERROR: Cannot read device info\n");
764 return;
765 }
766
767 if (memcmp(info->magic, DEVICE_MAGIC, DEVICE_MAGIC_SIZE))
768 {
769 memcpy(info->magic, DEVICE_MAGIC, DEVICE_MAGIC_SIZE);
770 info->is_unlocked = 0;
Shashank Mittala0032282011-08-26 14:50:11 -0700771 info->is_tampered = 0;
Shashank Mittal162244e2011-08-08 19:01:25 -0700772
773 write_device_info_mmc(info);
774 }
775 memcpy(dev, info, sizeof(device_info));
776}
777
778void write_device_info_flash(device_info *dev)
779{
780 struct device_info *info = (void *) info_buf;
781 struct ptentry *ptn;
782 struct ptable *ptable;
783
784 ptable = flash_get_ptable();
785 if (ptable == NULL)
786 {
787 dprintf(CRITICAL, "ERROR: Partition table not found\n");
788 return;
789 }
790
791 ptn = ptable_find(ptable, "devinfo");
792 if (ptn == NULL)
793 {
794 dprintf(CRITICAL, "ERROR: No boot partition found\n");
795 return;
796 }
797
798 memcpy(info, dev, sizeof(device_info));
799
800 if (flash_write(ptn, 0, (void *)info_buf, page_size))
801 {
802 dprintf(CRITICAL, "ERROR: Cannot write device info\n");
803 return;
804 }
805}
806
807void read_device_info_flash(device_info *dev)
808{
809 struct device_info *info = (void*) info_buf;
810 struct ptentry *ptn;
811 struct ptable *ptable;
812
813 ptable = flash_get_ptable();
814 if (ptable == NULL)
815 {
816 dprintf(CRITICAL, "ERROR: Partition table not found\n");
817 return;
818 }
819
820 ptn = ptable_find(ptable, "devinfo");
821 if (ptn == NULL)
822 {
823 dprintf(CRITICAL, "ERROR: No boot partition found\n");
824 return;
825 }
826
827 if (flash_read(ptn, 0, (void *)info_buf, page_size))
828 {
829 dprintf(CRITICAL, "ERROR: Cannot write device info\n");
830 return;
831 }
832
833 if (memcmp(info->magic, DEVICE_MAGIC, DEVICE_MAGIC_SIZE))
834 {
Shashank Mittal162244e2011-08-08 19:01:25 -0700835 memcpy(info->magic, DEVICE_MAGIC, DEVICE_MAGIC_SIZE);
836 info->is_unlocked = 0;
Shashank Mittala0032282011-08-26 14:50:11 -0700837 info->is_tampered = 0;
Shashank Mittal162244e2011-08-08 19:01:25 -0700838 write_device_info_flash(info);
839 }
840 memcpy(dev, info, sizeof(device_info));
841}
842
843void write_device_info(device_info *dev)
844{
845 if(target_is_emmc_boot())
846 {
847 write_device_info_mmc(dev);
848 }
849 else
850 {
851 write_device_info_flash(dev);
852 }
853}
854
855void read_device_info(device_info *dev)
856{
857 if(target_is_emmc_boot())
858 {
859 read_device_info_mmc(dev);
860 }
861 else
862 {
863 read_device_info_flash(dev);
864 }
865}
866
867void reset_device_info()
868{
869 dprintf(ALWAYS, "reset_device_info called.");
Shashank Mittala0032282011-08-26 14:50:11 -0700870 device.is_tampered = 0;
Shashank Mittal162244e2011-08-08 19:01:25 -0700871 write_device_info(&device);
872}
873
874void set_device_root()
875{
876 dprintf(ALWAYS, "set_device_root called.");
Shashank Mittala0032282011-08-26 14:50:11 -0700877 device.is_tampered = 1;
Shashank Mittal162244e2011-08-08 19:01:25 -0700878 write_device_info(&device);
879}
880
Brian Swetland9c4c0752009-01-25 16:23:50 -0800881void cmd_boot(const char *arg, void *data, unsigned sz)
882{
883 unsigned kernel_actual;
884 unsigned ramdisk_actual;
885 static struct boot_img_hdr hdr;
886 char *ptr = ((char*) data);
887
888 if (sz < sizeof(hdr)) {
889 fastboot_fail("invalid bootimage header");
890 return;
891 }
892
893 memcpy(&hdr, data, sizeof(hdr));
894
895 /* ensure commandline is terminated */
896 hdr.cmdline[BOOT_ARGS_SIZE-1] = 0;
897
Subbaraman Narayanamurthyfbe13a02010-09-10 11:51:12 -0700898 if(target_is_emmc_boot() && hdr.page_size) {
899 page_size = hdr.page_size;
900 page_mask = page_size - 1;
901 }
902
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800903 kernel_actual = ROUND_TO_PAGE(hdr.kernel_size, page_mask);
904 ramdisk_actual = ROUND_TO_PAGE(hdr.ramdisk_size, page_mask);
Brian Swetland9c4c0752009-01-25 16:23:50 -0800905
Shashank Mittal1f0e2662011-09-01 15:06:00 -0700906 /* sz should have atleast raw boot image */
907 if (page_size + kernel_actual + ramdisk_actual > sz) {
Brian Swetland9c4c0752009-01-25 16:23:50 -0800908 fastboot_fail("incomplete bootimage");
909 return;
910 }
911
Ajay Dudanie28a6072011-07-01 13:59:46 -0700912 memmove((void*) hdr.kernel_addr, ptr + page_size, hdr.kernel_size);
913 memmove((void*) hdr.ramdisk_addr, ptr + page_size + kernel_actual, hdr.ramdisk_size);
Brian Swetland9c4c0752009-01-25 16:23:50 -0800914
915 fastboot_okay("");
916 udc_stop();
917
Amol Jadie67872e2011-06-27 14:14:11 -0700918 boot_linux((void*) hdr.kernel_addr, (void*) hdr.tags_addr,
Chandan Uddaraju885e4db2009-12-03 22:45:26 -0800919 (const char*) hdr.cmdline, board_machtype(),
Ajay Dudanie28a6072011-07-01 13:59:46 -0700920 (void*) hdr.ramdisk_addr, hdr.ramdisk_size);
Brian Swetland9c4c0752009-01-25 16:23:50 -0800921}
922
Dima Zavin214cc642009-01-26 11:16:21 -0800923void cmd_erase(const char *arg, void *data, unsigned sz)
924{
925 struct ptentry *ptn;
926 struct ptable *ptable;
927
928 ptable = flash_get_ptable();
929 if (ptable == NULL) {
930 fastboot_fail("partition table doesn't exist");
931 return;
932 }
933
934 ptn = ptable_find(ptable, arg);
935 if (ptn == NULL) {
936 fastboot_fail("unknown partition name");
937 return;
938 }
939
940 if (flash_erase(ptn)) {
941 fastboot_fail("failed to erase partition");
942 return;
943 }
944 fastboot_okay("");
945}
946
Bikas Gurungd48bd242010-09-04 19:54:32 -0700947
948void cmd_erase_mmc(const char *arg, void *data, unsigned sz)
949{
950 unsigned long long ptn = 0;
neetidb4b24d62012-01-20 12:13:09 -0800951 unsigned int out[512] = {0};
Kinson Chikf1a43512011-07-14 11:28:39 -0700952 int index = INVALID_PTN;
Bikas Gurungd48bd242010-09-04 19:54:32 -0700953
Kinson Chikf1a43512011-07-14 11:28:39 -0700954 index = partition_get_index(arg);
955 ptn = partition_get_offset(index);
Neeti Desaica8c9602011-10-06 11:40:00 -0700956
Kinson Chikf1a43512011-07-14 11:28:39 -0700957 if(ptn == 0) {
Neeti Desaica8c9602011-10-06 11:40:00 -0700958 fastboot_fail("Partition table doesn't exist\n");
Bikas Gurungd48bd242010-09-04 19:54:32 -0700959 return;
960 }
neetidb4b24d62012-01-20 12:13:09 -0800961 /* Simple inefficient version of erase. Just writing
962 0 in first block */
963 if (mmc_write(ptn , 512, (unsigned int *)out)) {
964 fastboot_fail("failed to erase partition");
Bikas Gurungd48bd242010-09-04 19:54:32 -0700965 return;
966 }
967 fastboot_okay("");
968}
969
970
Ajay Dudani5c761132011-04-07 20:19:04 -0700971void cmd_flash_mmc_img(const char *arg, void *data, unsigned sz)
Shashank Mittal23b8f422010-04-16 19:27:21 -0700972{
973 unsigned long long ptn = 0;
Subbaraman Narayanamurthyc95b5b12010-08-31 13:19:48 -0700974 unsigned long long size = 0;
Kinson Chikf1a43512011-07-14 11:28:39 -0700975 int index = INVALID_PTN;
Subbaraman Narayanamurthyc95b5b12010-08-31 13:19:48 -0700976
Greg Grisco6e754772011-06-23 12:19:39 -0700977 if (!strcmp(arg, "partition"))
978 {
979 dprintf(INFO, "Attempt to write partition image.\n");
Neeti Desai5f26aff2011-09-30 10:27:40 -0700980 if (write_partition(sz, (unsigned char *) data)) {
Greg Grisco6e754772011-06-23 12:19:39 -0700981 fastboot_fail("failed to write partition");
Shashank Mittal23b8f422010-04-16 19:27:21 -0700982 return;
983 }
984 }
Greg Grisco6e754772011-06-23 12:19:39 -0700985 else
986 {
Kinson Chikf1a43512011-07-14 11:28:39 -0700987 index = partition_get_index(arg);
988 ptn = partition_get_offset(index);
Greg Grisco6e754772011-06-23 12:19:39 -0700989 if(ptn == 0) {
990 fastboot_fail("partition table doesn't exist");
991 return;
992 }
Shashank Mittal23b8f422010-04-16 19:27:21 -0700993
Greg Grisco6e754772011-06-23 12:19:39 -0700994 if (!strcmp(arg, "boot") || !strcmp(arg, "recovery")) {
995 if (memcmp((void *)data, BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
996 fastboot_fail("image is not a boot image");
997 return;
998 }
999 }
Subbaraman Narayanamurthyc95b5b12010-08-31 13:19:48 -07001000
Kinson Chikf1a43512011-07-14 11:28:39 -07001001 size = partition_get_size(index);
Greg Grisco6e754772011-06-23 12:19:39 -07001002 if (ROUND_TO_PAGE(sz,511) > size) {
1003 fastboot_fail("size too large");
1004 return;
1005 }
1006 else if (mmc_write(ptn , sz, (unsigned int *)data)) {
1007 fastboot_fail("flash write failure");
1008 return;
1009 }
Shashank Mittal23b8f422010-04-16 19:27:21 -07001010 }
1011 fastboot_okay("");
1012 return;
1013}
1014
Ajay Dudani5c761132011-04-07 20:19:04 -07001015void cmd_flash_mmc_sparse_img(const char *arg, void *data, unsigned sz)
1016{
1017 unsigned int chunk;
1018 unsigned int chunk_data_sz;
1019 sparse_header_t *sparse_header;
1020 chunk_header_t *chunk_header;
Ajay Dudaniab18f022011-05-12 14:39:22 -07001021 uint32_t total_blocks = 0;
Ajay Dudani5c761132011-04-07 20:19:04 -07001022 unsigned long long ptn = 0;
Channagoud Kadabi65b91002011-10-11 17:34:33 +05301023 unsigned long long size = 0;
Kinson Chikf1a43512011-07-14 11:28:39 -07001024 int index = INVALID_PTN;
Ajay Dudani5c761132011-04-07 20:19:04 -07001025
Kinson Chikf1a43512011-07-14 11:28:39 -07001026 index = partition_get_index(arg);
1027 ptn = partition_get_offset(index);
1028 if(ptn == 0) {
Ajay Dudani5c761132011-04-07 20:19:04 -07001029 fastboot_fail("partition table doesn't exist");
1030 return;
1031 }
1032
Channagoud Kadabi65b91002011-10-11 17:34:33 +05301033 size = partition_get_size(index);
1034 if (ROUND_TO_PAGE(sz,511) > size) {
1035 fastboot_fail("size too large");
1036 return;
1037 }
1038
Ajay Dudani5c761132011-04-07 20:19:04 -07001039 /* Read and skip over sparse image header */
1040 sparse_header = (sparse_header_t *) data;
1041 data += sparse_header->file_hdr_sz;
1042 if(sparse_header->file_hdr_sz > sizeof(sparse_header_t))
1043 {
1044 /* Skip the remaining bytes in a header that is longer than
1045 * we expected.
1046 */
1047 data += (sparse_header->file_hdr_sz - sizeof(sparse_header_t));
1048 }
1049
Ajay Dudanib06c05f2011-05-12 14:46:10 -07001050 dprintf (SPEW, "=== Sparse Image Header ===\n");
1051 dprintf (SPEW, "magic: 0x%x\n", sparse_header->magic);
1052 dprintf (SPEW, "major_version: 0x%x\n", sparse_header->major_version);
1053 dprintf (SPEW, "minor_version: 0x%x\n", sparse_header->minor_version);
1054 dprintf (SPEW, "file_hdr_sz: %d\n", sparse_header->file_hdr_sz);
1055 dprintf (SPEW, "chunk_hdr_sz: %d\n", sparse_header->chunk_hdr_sz);
1056 dprintf (SPEW, "blk_sz: %d\n", sparse_header->blk_sz);
1057 dprintf (SPEW, "total_blks: %d\n", sparse_header->total_blks);
1058 dprintf (SPEW, "total_chunks: %d\n", sparse_header->total_chunks);
Ajay Dudani5c761132011-04-07 20:19:04 -07001059
1060 /* Start processing chunks */
1061 for (chunk=0; chunk<sparse_header->total_chunks; chunk++)
1062 {
1063 /* Read and skip over chunk header */
1064 chunk_header = (chunk_header_t *) data;
1065 data += sizeof(chunk_header_t);
1066
1067 dprintf (SPEW, "=== Chunk Header ===\n");
1068 dprintf (SPEW, "chunk_type: 0x%x\n", chunk_header->chunk_type);
1069 dprintf (SPEW, "chunk_data_sz: 0x%x\n", chunk_header->chunk_sz);
1070 dprintf (SPEW, "total_size: 0x%x\n", chunk_header->total_sz);
1071
1072 if(sparse_header->chunk_hdr_sz > sizeof(chunk_header_t))
1073 {
1074 /* Skip the remaining bytes in a header that is longer than
1075 * we expected.
1076 */
1077 data += (sparse_header->chunk_hdr_sz - sizeof(chunk_header_t));
1078 }
1079
1080 chunk_data_sz = sparse_header->blk_sz * chunk_header->chunk_sz;
1081 switch (chunk_header->chunk_type)
1082 {
1083 case CHUNK_TYPE_RAW:
1084 if(chunk_header->total_sz != (sparse_header->chunk_hdr_sz +
1085 chunk_data_sz))
1086 {
1087 fastboot_fail("Bogus chunk size for chunk type Raw");
1088 return;
1089 }
1090
Ajay Dudaniab18f022011-05-12 14:39:22 -07001091 if(mmc_write(ptn + ((uint64_t)total_blocks*sparse_header->blk_sz),
1092 chunk_data_sz,
1093 (unsigned int*)data))
Ajay Dudani5c761132011-04-07 20:19:04 -07001094 {
1095 fastboot_fail("flash write failure");
1096 return;
1097 }
1098 total_blocks += chunk_header->chunk_sz;
1099 data += chunk_data_sz;
1100 break;
1101
1102 case CHUNK_TYPE_DONT_CARE:
Kinson Chik kchik@codeaurora.orgda29b1e2011-05-06 17:36:39 -07001103 total_blocks += chunk_header->chunk_sz;
1104 break;
1105
Ajay Dudani5c761132011-04-07 20:19:04 -07001106 case CHUNK_TYPE_CRC:
1107 if(chunk_header->total_sz != sparse_header->chunk_hdr_sz)
1108 {
1109 fastboot_fail("Bogus chunk size for chunk type Dont Care");
1110 return;
1111 }
1112 total_blocks += chunk_header->chunk_sz;
1113 data += chunk_data_sz;
1114 break;
1115
Kinson Chik kchik@codeaurora.orgda29b1e2011-05-06 17:36:39 -07001116 default:
Ajay Dudani5c761132011-04-07 20:19:04 -07001117 fastboot_fail("Unknown chunk type");
1118 return;
1119 }
1120 }
1121
Ajay Dudani0c6927b2011-05-18 11:12:16 -07001122 dprintf(INFO, "Wrote %d blocks, expected to write %d blocks\n",
1123 total_blocks, sparse_header->total_blks);
1124
1125 if(total_blocks != sparse_header->total_blks)
1126 {
1127 fastboot_fail("sparse image write failure");
1128 }
Ajay Dudani5c761132011-04-07 20:19:04 -07001129
1130 fastboot_okay("");
1131 return;
1132}
1133
1134void cmd_flash_mmc(const char *arg, void *data, unsigned sz)
1135{
1136 sparse_header_t *sparse_header;
kchik@codeaurora.orgbce18ea2011-04-18 20:22:28 -07001137 /* 8 Byte Magic + 2048 Byte xml + Encrypted Data */
1138 unsigned int *magic_number = (unsigned int *) data;
1139 int ret=0;
Ajay Dudani5c761132011-04-07 20:19:04 -07001140
Neeti Desai127b9e02012-03-20 16:11:23 -07001141 if (magic_number[0] == DECRYPT_MAGIC_0 &&
1142 magic_number[1] == DECRYPT_MAGIC_1)
kchik@codeaurora.orgbce18ea2011-04-18 20:22:28 -07001143 {
1144#ifdef SSD_ENABLE
Neeti Desai127b9e02012-03-20 16:11:23 -07001145 ret = decrypt_scm((uint32 **) &data, &sz);
kchik@codeaurora.orgbce18ea2011-04-18 20:22:28 -07001146#endif
Greg Griscod6250552011-06-29 14:40:23 -07001147 if (ret != 0) {
kchik@codeaurora.orgbce18ea2011-04-18 20:22:28 -07001148 dprintf(CRITICAL, "ERROR: Invalid secure image\n");
1149 return;
1150 }
1151 }
Neeti Desai127b9e02012-03-20 16:11:23 -07001152 else if (magic_number[0] == ENCRYPT_MAGIC_0 &&
1153 magic_number[1] == ENCRYPT_MAGIC_1)
1154 {
1155#ifdef SSD_ENABLE
1156 ret = encrypt_scm((uint32 **) &data, &sz);
1157#endif
1158 if (ret != 0) {
1159 dprintf(CRITICAL, "ERROR: Encryption Failure\n");
1160 return;
1161 }
1162 }
1163
kchik@codeaurora.orgbce18ea2011-04-18 20:22:28 -07001164 sparse_header = (sparse_header_t *) data;
Ajay Dudani5c761132011-04-07 20:19:04 -07001165 if (sparse_header->magic != SPARSE_HEADER_MAGIC)
1166 cmd_flash_mmc_img(arg, data, sz);
1167 else
1168 cmd_flash_mmc_sparse_img(arg, data, sz);
Ajay Dudani5c761132011-04-07 20:19:04 -07001169 return;
1170}
1171
Dima Zavin214cc642009-01-26 11:16:21 -08001172void cmd_flash(const char *arg, void *data, unsigned sz)
1173{
1174 struct ptentry *ptn;
1175 struct ptable *ptable;
1176 unsigned extra = 0;
1177
1178 ptable = flash_get_ptable();
1179 if (ptable == NULL) {
1180 fastboot_fail("partition table doesn't exist");
1181 return;
1182 }
1183
1184 ptn = ptable_find(ptable, arg);
1185 if (ptn == NULL) {
1186 fastboot_fail("unknown partition name");
1187 return;
1188 }
1189
1190 if (!strcmp(ptn->name, "boot") || !strcmp(ptn->name, "recovery")) {
1191 if (memcmp((void *)data, BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
1192 fastboot_fail("image is not a boot image");
1193 return;
1194 }
1195 }
1196
Amol Jadi5c61a952012-05-04 17:05:35 -07001197 if (!strcmp(ptn->name, "system")
Deepa Dinamani13e32c42012-03-12 14:34:17 -07001198 || !strcmp(ptn->name, "userdata")
1199 || !strcmp(ptn->name, "persist")
1200 || !strcmp(ptn->name, "recoveryfs")) {
Channagoud Kadabi404a7062011-03-21 19:27:50 +05301201 if (flash_ecc_bch_enabled())
1202 /* Spare data bytes for 8 bit ECC increased by 4 */
1203 extra = ((page_size >> 9) * 20);
1204 else
1205 extra = ((page_size >> 9) * 16);
1206 } else
Shashank Mittaldcc2e352009-11-19 19:11:16 -08001207 sz = ROUND_TO_PAGE(sz, page_mask);
Dima Zavin214cc642009-01-26 11:16:21 -08001208
1209 dprintf(INFO, "writing %d bytes to '%s'\n", sz, ptn->name);
1210 if (flash_write(ptn, extra, data, sz)) {
1211 fastboot_fail("flash write failure");
1212 return;
1213 }
1214 dprintf(INFO, "partition '%s' updated\n", ptn->name);
1215 fastboot_okay("");
1216}
1217
1218void cmd_continue(const char *arg, void *data, unsigned sz)
1219{
1220 fastboot_okay("");
1221 udc_stop();
Shashank Mittald8c42bf2010-06-09 15:44:28 -07001222 if (target_is_emmc_boot())
1223 {
1224 boot_linux_from_mmc();
1225 }
1226 else
1227 {
1228 boot_linux_from_flash();
1229 }
Dima Zavin214cc642009-01-26 11:16:21 -08001230}
1231
Chandan Uddaraju94183c02010-01-15 15:13:59 -08001232void cmd_reboot(const char *arg, void *data, unsigned sz)
1233{
Shashank Mittald8c42bf2010-06-09 15:44:28 -07001234 dprintf(INFO, "rebooting the device\n");
Chandan Uddaraju94183c02010-01-15 15:13:59 -08001235 fastboot_okay("");
1236 reboot_device(0);
1237}
1238
1239void cmd_reboot_bootloader(const char *arg, void *data, unsigned sz)
1240{
Shashank Mittald8c42bf2010-06-09 15:44:28 -07001241 dprintf(INFO, "rebooting the device\n");
Chandan Uddaraju94183c02010-01-15 15:13:59 -08001242 fastboot_okay("");
1243 reboot_device(FASTBOOT_MODE);
1244}
1245
Shashank Mittal162244e2011-08-08 19:01:25 -07001246void cmd_oem_unlock(const char *arg, void *data, unsigned sz)
1247{
1248 if(!device.is_unlocked)
1249 {
1250 device.is_unlocked = 1;
1251 write_device_info(&device);
1252 }
1253 fastboot_okay("");
1254}
1255
Shashank Mittala0032282011-08-26 14:50:11 -07001256void cmd_oem_devinfo(const char *arg, void *data, unsigned sz)
1257{
1258 char response[64];
1259 snprintf(response, 64, "\tDevice tampered: %s", (device.is_tampered ? "true" : "false"));
1260 fastboot_info(response);
1261 snprintf(response, 64, "\tDevice unlocked: %s", (device.is_unlocked ? "true" : "false"));
1262 fastboot_info(response);
1263 fastboot_okay("");
1264}
1265
Chandan Uddaraju2943fd62010-06-21 10:56:39 -07001266void splash_screen ()
1267{
1268 struct ptentry *ptn;
1269 struct ptable *ptable;
1270 struct fbcon_config *fb_display = NULL;
1271
1272 if (!target_is_emmc_boot())
1273 {
1274 ptable = flash_get_ptable();
1275 if (ptable == NULL) {
1276 dprintf(CRITICAL, "ERROR: Partition table not found\n");
Greg Griscod6250552011-06-29 14:40:23 -07001277 return;
Chandan Uddaraju2943fd62010-06-21 10:56:39 -07001278 }
1279
1280 ptn = ptable_find(ptable, "splash");
1281 if (ptn == NULL) {
1282 dprintf(CRITICAL, "ERROR: No splash partition found\n");
1283 } else {
1284 fb_display = fbcon_display();
1285 if (fb_display) {
1286 if (flash_read(ptn, 0, fb_display->base,
1287 (fb_display->width * fb_display->height * fb_display->bpp/8))) {
1288 fbcon_clear();
1289 dprintf(CRITICAL, "ERROR: Cannot read splash image\n");
1290 }
1291 }
1292 }
1293 }
1294}
1295
Brian Swetland9c4c0752009-01-25 16:23:50 -08001296void aboot_init(const struct app_descriptor *app)
1297{
Shashank Mittal4f99a882010-02-01 13:58:50 -08001298 unsigned reboot_mode = 0;
Shashank Mittald8c42bf2010-06-09 15:44:28 -07001299 unsigned usb_init = 0;
Vivek Mehta5f1c9d42011-04-01 20:11:59 -07001300 unsigned sz = 0;
Chandan Uddarajubedca152010-06-02 23:05:15 -07001301
Chandan Uddaraju2943fd62010-06-21 10:56:39 -07001302 /* Setup page size information for nand/emmc reads */
Shashank Mittald8c42bf2010-06-09 15:44:28 -07001303 if (target_is_emmc_boot())
1304 {
1305 page_size = 2048;
1306 page_mask = page_size - 1;
1307 }
1308 else
1309 {
1310 page_size = flash_page_size();
1311 page_mask = page_size - 1;
1312 }
1313
Shashank Mittal162244e2011-08-08 19:01:25 -07001314 if(target_use_signed_kernel())
1315 {
1316 read_device_info(&device);
1317
Shashank Mittal162244e2011-08-08 19:01:25 -07001318 }
1319
Greg Griscod6250552011-06-29 14:40:23 -07001320 target_serialno((unsigned char *) sn_buf);
Ajay Dudanib06c05f2011-05-12 14:46:10 -07001321 dprintf(SPEW,"serial number: %s\n",sn_buf);
Subbaraman Narayanamurthyf17b4ae2011-02-16 20:19:56 -08001322 surf_udc_device.serialno = sn_buf;
1323
Chandan Uddaraju2943fd62010-06-21 10:56:39 -07001324 /* Check if we should do something other than booting up */
Shashank Mittald8c42bf2010-06-09 15:44:28 -07001325 if (keys_get_state(KEY_HOME) != 0)
1326 boot_into_recovery = 1;
Wentao Xu153902c2010-12-20 16:20:52 -05001327 if (keys_get_state(KEY_VOLUMEUP) != 0)
1328 boot_into_recovery = 1;
Subbaraman Narayanamurthy0e445b02011-06-19 21:34:46 -07001329 if(!boot_into_recovery)
1330 {
1331 if (keys_get_state(KEY_BACK) != 0)
1332 goto fastboot;
1333 if (keys_get_state(KEY_VOLUMEDOWN) != 0)
1334 goto fastboot;
1335 }
Shashank Mittald8c42bf2010-06-09 15:44:28 -07001336
1337 #if NO_KEYPAD_DRIVER
Kinson Chik0b1c8162011-08-31 16:31:57 -07001338 if (fastboot_trigger())
Shashank Mittald8c42bf2010-06-09 15:44:28 -07001339 goto fastboot;
1340 #endif
Chandan Uddarajubedca152010-06-02 23:05:15 -07001341
Ajay Dudani77421292010-10-27 19:34:06 -07001342 reboot_mode = check_reboot_mode();
1343 if (reboot_mode == RECOVERY_MODE) {
1344 boot_into_recovery = 1;
1345 } else if(reboot_mode == FASTBOOT_MODE) {
1346 goto fastboot;
1347 }
1348
Shashank Mittal23b8f422010-04-16 19:27:21 -07001349 if (target_is_emmc_boot())
Shashank Mittald8c42bf2010-06-09 15:44:28 -07001350 {
Subbaraman Narayanamurthy0e445b02011-06-19 21:34:46 -07001351 if(emmc_recovery_init())
1352 dprintf(ALWAYS,"error in emmc_recovery_init\n");
Shashank Mittala0032282011-08-26 14:50:11 -07001353 if(target_use_signed_kernel())
1354 {
1355 if((device.is_unlocked) || (device.is_tampered))
1356 {
1357 #ifdef TZ_TAMPER_FUSE
1358 set_tamper_fuse_cmd();
1359 #endif
Channagoud Kadabibf695c62012-04-10 13:31:56 +05301360 #if USE_PCOM_SECBOOT
1361 set_tamper_flag(device.is_tampered);
1362 #endif
Shashank Mittala0032282011-08-26 14:50:11 -07001363 }
1364 }
Shashank Mittald8c42bf2010-06-09 15:44:28 -07001365 boot_linux_from_mmc();
1366 }
1367 else
1368 {
Shashank Mittald8c42bf2010-06-09 15:44:28 -07001369 recovery_init();
Channagoud Kadabie7b66702012-03-22 15:54:30 +05301370#if USE_PCOM_SECBOOT
1371 if((device.is_unlocked) || (device.is_tampered))
1372 set_tamper_flag(device.is_tampered);
1373#endif
Shashank Mittald8c42bf2010-06-09 15:44:28 -07001374 boot_linux_from_flash();
1375 }
Dima Zavinb4283602009-01-26 16:36:57 -08001376 dprintf(CRITICAL, "ERROR: Could not do normal boot. Reverting "
1377 "to fastboot mode.\n");
1378
1379fastboot:
Chandan Uddaraju2943fd62010-06-21 10:56:39 -07001380
Shashank Mittal162244e2011-08-08 19:01:25 -07001381 target_fastboot_init();
Amol Jadi57abe4c2011-05-24 15:47:27 -07001382
Shashank Mittald8c42bf2010-06-09 15:44:28 -07001383 if(!usb_init)
1384 udc_init(&surf_udc_device);
Brian Swetland9c4c0752009-01-25 16:23:50 -08001385
1386 fastboot_register("boot", cmd_boot);
Bikas Gurungd48bd242010-09-04 19:54:32 -07001387
Shashank Mittal23b8f422010-04-16 19:27:21 -07001388 if (target_is_emmc_boot())
Shashank Mittald8c42bf2010-06-09 15:44:28 -07001389 {
1390 fastboot_register("flash:", cmd_flash_mmc);
Bikas Gurungd48bd242010-09-04 19:54:32 -07001391 fastboot_register("erase:", cmd_erase_mmc);
Shashank Mittald8c42bf2010-06-09 15:44:28 -07001392 }
1393 else
1394 {
1395 fastboot_register("flash:", cmd_flash);
Bikas Gurungd48bd242010-09-04 19:54:32 -07001396 fastboot_register("erase:", cmd_erase);
Shashank Mittald8c42bf2010-06-09 15:44:28 -07001397 }
1398
1399 fastboot_register("continue", cmd_continue);
Chandan Uddaraju94183c02010-01-15 15:13:59 -08001400 fastboot_register("reboot", cmd_reboot);
1401 fastboot_register("reboot-bootloader", cmd_reboot_bootloader);
Shashank Mittal162244e2011-08-08 19:01:25 -07001402 fastboot_register("oem unlock", cmd_oem_unlock);
Shashank Mittala0032282011-08-26 14:50:11 -07001403 fastboot_register("oem device-info", cmd_oem_devinfo);
Subbaraman Narayanamurthyeb92bcc2010-07-20 14:32:46 -07001404 fastboot_publish("product", TARGET(BOARD));
Brian Swetland9c4c0752009-01-25 16:23:50 -08001405 fastboot_publish("kernel", "lk");
Trevor Bourget59b25d52012-01-13 18:43:36 -08001406 fastboot_publish("serialno", sn_buf);
Kinson Chikf1a43512011-07-14 11:28:39 -07001407 partition_dump();
Vivek Mehta5f1c9d42011-04-01 20:11:59 -07001408 sz = target_get_max_flash_size();
1409 fastboot_init(target_get_scratch_address(), sz);
Brian Swetland9c4c0752009-01-25 16:23:50 -08001410 udc_start();
Brian Swetland9c4c0752009-01-25 16:23:50 -08001411}
1412
1413APP_START(aboot)
1414 .init = aboot_init,
1415APP_END
1416
Neeti Desai17379b82012-06-04 18:42:53 -07001417#if DEVICE_TREE
1418/* Device Tree Stuff */
1419int update_device_tree(const void * fdt, char *cmdline,
1420 void *ramdisk, unsigned ramdisk_size)
1421{
1422 int ret = 0;
1423 int offset;
1424 uint32_t *memory_reg;
1425 unsigned char *final_cmdline;
1426 uint32_t len;
1427
1428 /* Check the device tree header */
1429 ret = fdt_check_header(fdt);
1430 if(ret)
1431 {
1432 dprintf(CRITICAL, "Invalid device tree header \n");
1433 return ret;
1434 }
1435
1436 /* Get offset of the memory node */
1437 offset = fdt_path_offset(fdt,"/memory");
1438
1439 memory_reg = target_dev_tree_mem(&len);
1440
1441 /* Adding the memory values to the reg property */
1442 ret = fdt_setprop(fdt, offset, "reg", memory_reg, sizeof(uint32_t) * len * 2);
1443 if(ret)
1444 {
1445 dprintf(CRITICAL, "ERROR: Cannot update memory node\n");
1446 return ret;
1447 }
1448
1449 /* Get offset of the chosen node */
1450 offset = fdt_path_offset(fdt, "/chosen");
1451
1452 /* Adding the cmdline to the chosen node */
1453 final_cmdline = update_cmdline(cmdline);
1454 ret = fdt_setprop_string(fdt, offset, "bootargs", final_cmdline);
1455 if(ret)
1456 {
1457 dprintf(CRITICAL, "ERROR: Cannot update chosen node [bootargs]\n");
1458 return ret;
1459 }
1460
1461 /* Adding the initrd-start to the chosen node */
1462 ret = fdt_setprop_cell(fdt, offset, "linux,initrd-start", ramdisk);
1463 if(ret)
1464 {
1465 dprintf(CRITICAL, "ERROR: Cannot update chosen node [linux,initrd-start]\n");
1466 return ret;
1467 }
1468
1469 /* Adding the initrd-end to the chosen node */
1470 ret = fdt_setprop_cell(fdt, offset, "linux,initrd-end", (ramdisk + ramdisk_size));
1471 if(ret)
1472 {
1473 dprintf(CRITICAL, "ERROR: Cannot update chosen node [linux,initrd-end]\n");
1474 return ret;
1475 }
1476
1477 fdt_pack(fdt);
1478
1479 return ret;
1480}
1481#endif