blob: 19d51a8d5686a7a512e74ebcbcd47b5d6e00775d [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 }
Shashank Mittalcd98d472011-08-02 14:29:24 -0700570 }
571 else
572 {
Shashank Mittal162244e2011-08-08 19:01:25 -0700573 offset = page_size;
574
Shashank Mittalcd98d472011-08-02 14:29:24 -0700575 n = ROUND_TO_PAGE(hdr->kernel_size, page_mask);
576 if (flash_read(ptn, offset, (void *)hdr->kernel_addr, n)) {
577 dprintf(CRITICAL, "ERROR: Cannot read kernel image\n");
578 return -1;
579 }
580 offset += n;
581
582 n = ROUND_TO_PAGE(hdr->ramdisk_size, page_mask);
583 if (flash_read(ptn, offset, (void *)hdr->ramdisk_addr, n)) {
584 dprintf(CRITICAL, "ERROR: Cannot read ramdisk image\n");
585 return -1;
586 }
587 offset += n;
588 }
David Ng183a7422009-12-07 14:55:21 -0800589continue_boot:
Dima Zavin214cc642009-01-26 11:16:21 -0800590 dprintf(INFO, "\nkernel @ %x (%d bytes)\n", hdr->kernel_addr,
591 hdr->kernel_size);
592 dprintf(INFO, "ramdisk @ %x (%d bytes)\n", hdr->ramdisk_addr,
593 hdr->ramdisk_size);
594
595 if(hdr->cmdline[0]) {
596 cmdline = (char*) hdr->cmdline;
597 } else {
598 cmdline = DEFAULT_CMDLINE;
599 }
600 dprintf(INFO, "cmdline = '%s'\n", cmdline);
601
602 /* TODO: create/pass atags to kernel */
603
604 dprintf(INFO, "\nBooting Linux\n");
Ajay Dudanie28a6072011-07-01 13:59:46 -0700605 boot_linux((void *)hdr->kernel_addr, (void *)hdr->tags_addr,
Chandan Uddaraju885e4db2009-12-03 22:45:26 -0800606 (const char *)cmdline, board_machtype(),
Dima Zavin214cc642009-01-26 11:16:21 -0800607 (void *)hdr->ramdisk_addr, hdr->ramdisk_size);
608
609 return 0;
610}
Brian Swetland9c4c0752009-01-25 16:23:50 -0800611
Shashank Mittal162244e2011-08-08 19:01:25 -0700612unsigned char info_buf[4096];
613void write_device_info_mmc(device_info *dev)
614{
615 struct device_info *info = (void*) info_buf;
616 unsigned long long ptn = 0;
617 unsigned long long size;
618 int index = INVALID_PTN;
619
620 index = partition_get_index("aboot");
621 ptn = partition_get_offset(index);
622 if(ptn == 0)
623 {
624 return;
625 }
626
627 size = partition_get_size(index);
628
629 memcpy(info, dev, sizeof(device_info));
630
631 if(mmc_write((ptn + size - 512), 512, (void *)info_buf))
632 {
633 dprintf(CRITICAL, "ERROR: Cannot write device info\n");
634 return;
635 }
636}
637
638void read_device_info_mmc(device_info *dev)
639{
640 struct device_info *info = (void*) info_buf;
641 unsigned long long ptn = 0;
642 unsigned long long size;
643 int index = INVALID_PTN;
644
645 index = partition_get_index("aboot");
646 ptn = partition_get_offset(index);
647 if(ptn == 0)
648 {
649 return;
650 }
651
652 size = partition_get_size(index);
653
654 if(mmc_read((ptn + size - 512), (void *)info_buf, 512))
655 {
656 dprintf(CRITICAL, "ERROR: Cannot read device info\n");
657 return;
658 }
659
660 if (memcmp(info->magic, DEVICE_MAGIC, DEVICE_MAGIC_SIZE))
661 {
662 memcpy(info->magic, DEVICE_MAGIC, DEVICE_MAGIC_SIZE);
663 info->is_unlocked = 0;
Shashank Mittala0032282011-08-26 14:50:11 -0700664 info->is_tampered = 0;
Shashank Mittal162244e2011-08-08 19:01:25 -0700665
666 write_device_info_mmc(info);
667 }
668 memcpy(dev, info, sizeof(device_info));
669}
670
671void write_device_info_flash(device_info *dev)
672{
673 struct device_info *info = (void *) info_buf;
674 struct ptentry *ptn;
675 struct ptable *ptable;
676
677 ptable = flash_get_ptable();
678 if (ptable == NULL)
679 {
680 dprintf(CRITICAL, "ERROR: Partition table not found\n");
681 return;
682 }
683
684 ptn = ptable_find(ptable, "devinfo");
685 if (ptn == NULL)
686 {
687 dprintf(CRITICAL, "ERROR: No boot partition found\n");
688 return;
689 }
690
691 memcpy(info, dev, sizeof(device_info));
692
693 if (flash_write(ptn, 0, (void *)info_buf, page_size))
694 {
695 dprintf(CRITICAL, "ERROR: Cannot write device info\n");
696 return;
697 }
698}
699
700void read_device_info_flash(device_info *dev)
701{
702 struct device_info *info = (void*) info_buf;
703 struct ptentry *ptn;
704 struct ptable *ptable;
705
706 ptable = flash_get_ptable();
707 if (ptable == NULL)
708 {
709 dprintf(CRITICAL, "ERROR: Partition table not found\n");
710 return;
711 }
712
713 ptn = ptable_find(ptable, "devinfo");
714 if (ptn == NULL)
715 {
716 dprintf(CRITICAL, "ERROR: No boot partition found\n");
717 return;
718 }
719
720 if (flash_read(ptn, 0, (void *)info_buf, page_size))
721 {
722 dprintf(CRITICAL, "ERROR: Cannot write device info\n");
723 return;
724 }
725
726 if (memcmp(info->magic, DEVICE_MAGIC, DEVICE_MAGIC_SIZE))
727 {
728 while(1);
729 memcpy(info->magic, DEVICE_MAGIC, DEVICE_MAGIC_SIZE);
730 info->is_unlocked = 0;
Shashank Mittala0032282011-08-26 14:50:11 -0700731 info->is_tampered = 0;
Shashank Mittal162244e2011-08-08 19:01:25 -0700732 write_device_info_flash(info);
733 }
734 memcpy(dev, info, sizeof(device_info));
735}
736
737void write_device_info(device_info *dev)
738{
739 if(target_is_emmc_boot())
740 {
741 write_device_info_mmc(dev);
742 }
743 else
744 {
745 write_device_info_flash(dev);
746 }
747}
748
749void read_device_info(device_info *dev)
750{
751 if(target_is_emmc_boot())
752 {
753 read_device_info_mmc(dev);
754 }
755 else
756 {
757 read_device_info_flash(dev);
758 }
759}
760
761void reset_device_info()
762{
763 dprintf(ALWAYS, "reset_device_info called.");
Shashank Mittala0032282011-08-26 14:50:11 -0700764 device.is_tampered = 0;
Shashank Mittal162244e2011-08-08 19:01:25 -0700765 write_device_info(&device);
766}
767
768void set_device_root()
769{
770 dprintf(ALWAYS, "set_device_root called.");
Shashank Mittala0032282011-08-26 14:50:11 -0700771 device.is_tampered = 1;
Shashank Mittal162244e2011-08-08 19:01:25 -0700772 write_device_info(&device);
773}
774
Brian Swetland9c4c0752009-01-25 16:23:50 -0800775void cmd_boot(const char *arg, void *data, unsigned sz)
776{
777 unsigned kernel_actual;
778 unsigned ramdisk_actual;
779 static struct boot_img_hdr hdr;
780 char *ptr = ((char*) data);
781
782 if (sz < sizeof(hdr)) {
783 fastboot_fail("invalid bootimage header");
784 return;
785 }
786
787 memcpy(&hdr, data, sizeof(hdr));
788
789 /* ensure commandline is terminated */
790 hdr.cmdline[BOOT_ARGS_SIZE-1] = 0;
791
Subbaraman Narayanamurthyfbe13a02010-09-10 11:51:12 -0700792 if(target_is_emmc_boot() && hdr.page_size) {
793 page_size = hdr.page_size;
794 page_mask = page_size - 1;
795 }
796
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800797 kernel_actual = ROUND_TO_PAGE(hdr.kernel_size, page_mask);
798 ramdisk_actual = ROUND_TO_PAGE(hdr.ramdisk_size, page_mask);
Brian Swetland9c4c0752009-01-25 16:23:50 -0800799
Shashank Mittal1f0e2662011-09-01 15:06:00 -0700800 /* sz should have atleast raw boot image */
801 if (page_size + kernel_actual + ramdisk_actual > sz) {
Brian Swetland9c4c0752009-01-25 16:23:50 -0800802 fastboot_fail("incomplete bootimage");
803 return;
804 }
805
Ajay Dudanie28a6072011-07-01 13:59:46 -0700806 memmove((void*) hdr.kernel_addr, ptr + page_size, hdr.kernel_size);
807 memmove((void*) hdr.ramdisk_addr, ptr + page_size + kernel_actual, hdr.ramdisk_size);
Brian Swetland9c4c0752009-01-25 16:23:50 -0800808
809 fastboot_okay("");
810 udc_stop();
811
Amol Jadie67872e2011-06-27 14:14:11 -0700812 boot_linux((void*) hdr.kernel_addr, (void*) hdr.tags_addr,
Chandan Uddaraju885e4db2009-12-03 22:45:26 -0800813 (const char*) hdr.cmdline, board_machtype(),
Ajay Dudanie28a6072011-07-01 13:59:46 -0700814 (void*) hdr.ramdisk_addr, hdr.ramdisk_size);
Brian Swetland9c4c0752009-01-25 16:23:50 -0800815}
816
Dima Zavin214cc642009-01-26 11:16:21 -0800817void cmd_erase(const char *arg, void *data, unsigned sz)
818{
819 struct ptentry *ptn;
820 struct ptable *ptable;
821
822 ptable = flash_get_ptable();
823 if (ptable == NULL) {
824 fastboot_fail("partition table doesn't exist");
825 return;
826 }
827
828 ptn = ptable_find(ptable, arg);
829 if (ptn == NULL) {
830 fastboot_fail("unknown partition name");
831 return;
832 }
833
834 if (flash_erase(ptn)) {
835 fastboot_fail("failed to erase partition");
836 return;
837 }
838 fastboot_okay("");
839}
840
Bikas Gurungd48bd242010-09-04 19:54:32 -0700841
842void cmd_erase_mmc(const char *arg, void *data, unsigned sz)
843{
844 unsigned long long ptn = 0;
neetidb4b24d62012-01-20 12:13:09 -0800845 unsigned int out[512] = {0};
Kinson Chikf1a43512011-07-14 11:28:39 -0700846 int index = INVALID_PTN;
Bikas Gurungd48bd242010-09-04 19:54:32 -0700847
Kinson Chikf1a43512011-07-14 11:28:39 -0700848 index = partition_get_index(arg);
849 ptn = partition_get_offset(index);
Neeti Desaica8c9602011-10-06 11:40:00 -0700850
Kinson Chikf1a43512011-07-14 11:28:39 -0700851 if(ptn == 0) {
Neeti Desaica8c9602011-10-06 11:40:00 -0700852 fastboot_fail("Partition table doesn't exist\n");
Bikas Gurungd48bd242010-09-04 19:54:32 -0700853 return;
854 }
neetidb4b24d62012-01-20 12:13:09 -0800855 /* Simple inefficient version of erase. Just writing
856 0 in first block */
857 if (mmc_write(ptn , 512, (unsigned int *)out)) {
858 fastboot_fail("failed to erase partition");
Bikas Gurungd48bd242010-09-04 19:54:32 -0700859 return;
860 }
861 fastboot_okay("");
862}
863
864
Ajay Dudani5c761132011-04-07 20:19:04 -0700865void cmd_flash_mmc_img(const char *arg, void *data, unsigned sz)
Shashank Mittal23b8f422010-04-16 19:27:21 -0700866{
867 unsigned long long ptn = 0;
Subbaraman Narayanamurthyc95b5b12010-08-31 13:19:48 -0700868 unsigned long long size = 0;
Kinson Chikf1a43512011-07-14 11:28:39 -0700869 int index = INVALID_PTN;
Subbaraman Narayanamurthyc95b5b12010-08-31 13:19:48 -0700870
Greg Grisco6e754772011-06-23 12:19:39 -0700871 if (!strcmp(arg, "partition"))
872 {
873 dprintf(INFO, "Attempt to write partition image.\n");
Neeti Desai5f26aff2011-09-30 10:27:40 -0700874 if (write_partition(sz, (unsigned char *) data)) {
Greg Grisco6e754772011-06-23 12:19:39 -0700875 fastboot_fail("failed to write partition");
Shashank Mittal23b8f422010-04-16 19:27:21 -0700876 return;
877 }
878 }
Greg Grisco6e754772011-06-23 12:19:39 -0700879 else
880 {
Kinson Chikf1a43512011-07-14 11:28:39 -0700881 index = partition_get_index(arg);
882 ptn = partition_get_offset(index);
Greg Grisco6e754772011-06-23 12:19:39 -0700883 if(ptn == 0) {
884 fastboot_fail("partition table doesn't exist");
885 return;
886 }
Shashank Mittal23b8f422010-04-16 19:27:21 -0700887
Greg Grisco6e754772011-06-23 12:19:39 -0700888 if (!strcmp(arg, "boot") || !strcmp(arg, "recovery")) {
889 if (memcmp((void *)data, BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
890 fastboot_fail("image is not a boot image");
891 return;
892 }
893 }
Subbaraman Narayanamurthyc95b5b12010-08-31 13:19:48 -0700894
Kinson Chikf1a43512011-07-14 11:28:39 -0700895 size = partition_get_size(index);
Greg Grisco6e754772011-06-23 12:19:39 -0700896 if (ROUND_TO_PAGE(sz,511) > size) {
897 fastboot_fail("size too large");
898 return;
899 }
900 else if (mmc_write(ptn , sz, (unsigned int *)data)) {
901 fastboot_fail("flash write failure");
902 return;
903 }
Shashank Mittal23b8f422010-04-16 19:27:21 -0700904 }
905 fastboot_okay("");
906 return;
907}
908
Ajay Dudani5c761132011-04-07 20:19:04 -0700909void cmd_flash_mmc_sparse_img(const char *arg, void *data, unsigned sz)
910{
911 unsigned int chunk;
912 unsigned int chunk_data_sz;
913 sparse_header_t *sparse_header;
914 chunk_header_t *chunk_header;
Ajay Dudaniab18f022011-05-12 14:39:22 -0700915 uint32_t total_blocks = 0;
Ajay Dudani5c761132011-04-07 20:19:04 -0700916 unsigned long long ptn = 0;
Channagoud Kadabi65b91002011-10-11 17:34:33 +0530917 unsigned long long size = 0;
Kinson Chikf1a43512011-07-14 11:28:39 -0700918 int index = INVALID_PTN;
Ajay Dudani5c761132011-04-07 20:19:04 -0700919
Kinson Chikf1a43512011-07-14 11:28:39 -0700920 index = partition_get_index(arg);
921 ptn = partition_get_offset(index);
922 if(ptn == 0) {
Ajay Dudani5c761132011-04-07 20:19:04 -0700923 fastboot_fail("partition table doesn't exist");
924 return;
925 }
926
Channagoud Kadabi65b91002011-10-11 17:34:33 +0530927 size = partition_get_size(index);
928 if (ROUND_TO_PAGE(sz,511) > size) {
929 fastboot_fail("size too large");
930 return;
931 }
932
Ajay Dudani5c761132011-04-07 20:19:04 -0700933 /* Read and skip over sparse image header */
934 sparse_header = (sparse_header_t *) data;
935 data += sparse_header->file_hdr_sz;
936 if(sparse_header->file_hdr_sz > sizeof(sparse_header_t))
937 {
938 /* Skip the remaining bytes in a header that is longer than
939 * we expected.
940 */
941 data += (sparse_header->file_hdr_sz - sizeof(sparse_header_t));
942 }
943
Ajay Dudanib06c05f2011-05-12 14:46:10 -0700944 dprintf (SPEW, "=== Sparse Image Header ===\n");
945 dprintf (SPEW, "magic: 0x%x\n", sparse_header->magic);
946 dprintf (SPEW, "major_version: 0x%x\n", sparse_header->major_version);
947 dprintf (SPEW, "minor_version: 0x%x\n", sparse_header->minor_version);
948 dprintf (SPEW, "file_hdr_sz: %d\n", sparse_header->file_hdr_sz);
949 dprintf (SPEW, "chunk_hdr_sz: %d\n", sparse_header->chunk_hdr_sz);
950 dprintf (SPEW, "blk_sz: %d\n", sparse_header->blk_sz);
951 dprintf (SPEW, "total_blks: %d\n", sparse_header->total_blks);
952 dprintf (SPEW, "total_chunks: %d\n", sparse_header->total_chunks);
Ajay Dudani5c761132011-04-07 20:19:04 -0700953
954 /* Start processing chunks */
955 for (chunk=0; chunk<sparse_header->total_chunks; chunk++)
956 {
957 /* Read and skip over chunk header */
958 chunk_header = (chunk_header_t *) data;
959 data += sizeof(chunk_header_t);
960
961 dprintf (SPEW, "=== Chunk Header ===\n");
962 dprintf (SPEW, "chunk_type: 0x%x\n", chunk_header->chunk_type);
963 dprintf (SPEW, "chunk_data_sz: 0x%x\n", chunk_header->chunk_sz);
964 dprintf (SPEW, "total_size: 0x%x\n", chunk_header->total_sz);
965
966 if(sparse_header->chunk_hdr_sz > sizeof(chunk_header_t))
967 {
968 /* Skip the remaining bytes in a header that is longer than
969 * we expected.
970 */
971 data += (sparse_header->chunk_hdr_sz - sizeof(chunk_header_t));
972 }
973
974 chunk_data_sz = sparse_header->blk_sz * chunk_header->chunk_sz;
975 switch (chunk_header->chunk_type)
976 {
977 case CHUNK_TYPE_RAW:
978 if(chunk_header->total_sz != (sparse_header->chunk_hdr_sz +
979 chunk_data_sz))
980 {
981 fastboot_fail("Bogus chunk size for chunk type Raw");
982 return;
983 }
984
Ajay Dudaniab18f022011-05-12 14:39:22 -0700985 if(mmc_write(ptn + ((uint64_t)total_blocks*sparse_header->blk_sz),
986 chunk_data_sz,
987 (unsigned int*)data))
Ajay Dudani5c761132011-04-07 20:19:04 -0700988 {
989 fastboot_fail("flash write failure");
990 return;
991 }
992 total_blocks += chunk_header->chunk_sz;
993 data += chunk_data_sz;
994 break;
995
996 case CHUNK_TYPE_DONT_CARE:
Kinson Chik kchik@codeaurora.orgda29b1e2011-05-06 17:36:39 -0700997 total_blocks += chunk_header->chunk_sz;
998 break;
999
Ajay Dudani5c761132011-04-07 20:19:04 -07001000 case CHUNK_TYPE_CRC:
1001 if(chunk_header->total_sz != sparse_header->chunk_hdr_sz)
1002 {
1003 fastboot_fail("Bogus chunk size for chunk type Dont Care");
1004 return;
1005 }
1006 total_blocks += chunk_header->chunk_sz;
1007 data += chunk_data_sz;
1008 break;
1009
Kinson Chik kchik@codeaurora.orgda29b1e2011-05-06 17:36:39 -07001010 default:
Ajay Dudani5c761132011-04-07 20:19:04 -07001011 fastboot_fail("Unknown chunk type");
1012 return;
1013 }
1014 }
1015
Ajay Dudani0c6927b2011-05-18 11:12:16 -07001016 dprintf(INFO, "Wrote %d blocks, expected to write %d blocks\n",
1017 total_blocks, sparse_header->total_blks);
1018
1019 if(total_blocks != sparse_header->total_blks)
1020 {
1021 fastboot_fail("sparse image write failure");
1022 }
Ajay Dudani5c761132011-04-07 20:19:04 -07001023
1024 fastboot_okay("");
1025 return;
1026}
1027
1028void cmd_flash_mmc(const char *arg, void *data, unsigned sz)
1029{
1030 sparse_header_t *sparse_header;
kchik@codeaurora.orgbce18ea2011-04-18 20:22:28 -07001031 /* 8 Byte Magic + 2048 Byte xml + Encrypted Data */
1032 unsigned int *magic_number = (unsigned int *) data;
1033 int ret=0;
Ajay Dudani5c761132011-04-07 20:19:04 -07001034
kchik@codeaurora.orgbce18ea2011-04-18 20:22:28 -07001035 if (magic_number[0] == SSD_HEADER_MAGIC_0 &&
1036 magic_number[1] == SSD_HEADER_MAGIC_1)
1037 {
1038#ifdef SSD_ENABLE
Greg Griscod6250552011-06-29 14:40:23 -07001039 ret = decrypt_img_scm((uint32 **) &data, &sz);
kchik@codeaurora.orgbce18ea2011-04-18 20:22:28 -07001040#endif
Greg Griscod6250552011-06-29 14:40:23 -07001041 if (ret != 0) {
kchik@codeaurora.orgbce18ea2011-04-18 20:22:28 -07001042 dprintf(CRITICAL, "ERROR: Invalid secure image\n");
1043 return;
1044 }
1045 }
1046 sparse_header = (sparse_header_t *) data;
Ajay Dudani5c761132011-04-07 20:19:04 -07001047 if (sparse_header->magic != SPARSE_HEADER_MAGIC)
1048 cmd_flash_mmc_img(arg, data, sz);
1049 else
1050 cmd_flash_mmc_sparse_img(arg, data, sz);
Ajay Dudani5c761132011-04-07 20:19:04 -07001051 return;
1052}
1053
Dima Zavin214cc642009-01-26 11:16:21 -08001054void cmd_flash(const char *arg, void *data, unsigned sz)
1055{
1056 struct ptentry *ptn;
1057 struct ptable *ptable;
1058 unsigned extra = 0;
1059
1060 ptable = flash_get_ptable();
1061 if (ptable == NULL) {
1062 fastboot_fail("partition table doesn't exist");
1063 return;
1064 }
1065
1066 ptn = ptable_find(ptable, arg);
1067 if (ptn == NULL) {
1068 fastboot_fail("unknown partition name");
1069 return;
1070 }
1071
1072 if (!strcmp(ptn->name, "boot") || !strcmp(ptn->name, "recovery")) {
1073 if (memcmp((void *)data, BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
1074 fastboot_fail("image is not a boot image");
1075 return;
1076 }
1077 }
1078
Chandan Uddarajud6d45042010-02-24 21:12:45 -08001079 if (!strcmp(ptn->name, "system") || !strcmp(ptn->name, "userdata")
Channagoud Kadabi404a7062011-03-21 19:27:50 +05301080 || !strcmp(ptn->name, "persist")) {
1081 if (flash_ecc_bch_enabled())
1082 /* Spare data bytes for 8 bit ECC increased by 4 */
1083 extra = ((page_size >> 9) * 20);
1084 else
1085 extra = ((page_size >> 9) * 16);
1086 } else
Shashank Mittaldcc2e352009-11-19 19:11:16 -08001087 sz = ROUND_TO_PAGE(sz, page_mask);
Dima Zavin214cc642009-01-26 11:16:21 -08001088
1089 dprintf(INFO, "writing %d bytes to '%s'\n", sz, ptn->name);
1090 if (flash_write(ptn, extra, data, sz)) {
1091 fastboot_fail("flash write failure");
1092 return;
1093 }
1094 dprintf(INFO, "partition '%s' updated\n", ptn->name);
1095 fastboot_okay("");
1096}
1097
1098void cmd_continue(const char *arg, void *data, unsigned sz)
1099{
1100 fastboot_okay("");
1101 udc_stop();
Shashank Mittald8c42bf2010-06-09 15:44:28 -07001102 if (target_is_emmc_boot())
1103 {
1104 boot_linux_from_mmc();
1105 }
1106 else
1107 {
1108 boot_linux_from_flash();
1109 }
Dima Zavin214cc642009-01-26 11:16:21 -08001110}
1111
Chandan Uddaraju94183c02010-01-15 15:13:59 -08001112void cmd_reboot(const char *arg, void *data, unsigned sz)
1113{
Shashank Mittald8c42bf2010-06-09 15:44:28 -07001114 dprintf(INFO, "rebooting the device\n");
Chandan Uddaraju94183c02010-01-15 15:13:59 -08001115 fastboot_okay("");
1116 reboot_device(0);
1117}
1118
1119void cmd_reboot_bootloader(const char *arg, void *data, unsigned sz)
1120{
Shashank Mittald8c42bf2010-06-09 15:44:28 -07001121 dprintf(INFO, "rebooting the device\n");
Chandan Uddaraju94183c02010-01-15 15:13:59 -08001122 fastboot_okay("");
1123 reboot_device(FASTBOOT_MODE);
1124}
1125
Shashank Mittal162244e2011-08-08 19:01:25 -07001126void cmd_oem_unlock(const char *arg, void *data, unsigned sz)
1127{
1128 if(!device.is_unlocked)
1129 {
1130 device.is_unlocked = 1;
1131 write_device_info(&device);
1132 }
1133 fastboot_okay("");
1134}
1135
Shashank Mittala0032282011-08-26 14:50:11 -07001136void cmd_oem_devinfo(const char *arg, void *data, unsigned sz)
1137{
1138 char response[64];
1139 snprintf(response, 64, "\tDevice tampered: %s", (device.is_tampered ? "true" : "false"));
1140 fastboot_info(response);
1141 snprintf(response, 64, "\tDevice unlocked: %s", (device.is_unlocked ? "true" : "false"));
1142 fastboot_info(response);
1143 fastboot_okay("");
1144}
1145
Chandan Uddaraju2943fd62010-06-21 10:56:39 -07001146void splash_screen ()
1147{
1148 struct ptentry *ptn;
1149 struct ptable *ptable;
1150 struct fbcon_config *fb_display = NULL;
1151
1152 if (!target_is_emmc_boot())
1153 {
1154 ptable = flash_get_ptable();
1155 if (ptable == NULL) {
1156 dprintf(CRITICAL, "ERROR: Partition table not found\n");
Greg Griscod6250552011-06-29 14:40:23 -07001157 return;
Chandan Uddaraju2943fd62010-06-21 10:56:39 -07001158 }
1159
1160 ptn = ptable_find(ptable, "splash");
1161 if (ptn == NULL) {
1162 dprintf(CRITICAL, "ERROR: No splash partition found\n");
1163 } else {
1164 fb_display = fbcon_display();
1165 if (fb_display) {
1166 if (flash_read(ptn, 0, fb_display->base,
1167 (fb_display->width * fb_display->height * fb_display->bpp/8))) {
1168 fbcon_clear();
1169 dprintf(CRITICAL, "ERROR: Cannot read splash image\n");
1170 }
1171 }
1172 }
1173 }
1174}
1175
Brian Swetland9c4c0752009-01-25 16:23:50 -08001176void aboot_init(const struct app_descriptor *app)
1177{
Shashank Mittal4f99a882010-02-01 13:58:50 -08001178 unsigned reboot_mode = 0;
Shashank Mittald8c42bf2010-06-09 15:44:28 -07001179 unsigned usb_init = 0;
Vivek Mehta5f1c9d42011-04-01 20:11:59 -07001180 unsigned sz = 0;
Chandan Uddarajubedca152010-06-02 23:05:15 -07001181
Chandan Uddaraju2943fd62010-06-21 10:56:39 -07001182 /* Setup page size information for nand/emmc reads */
Shashank Mittald8c42bf2010-06-09 15:44:28 -07001183 if (target_is_emmc_boot())
1184 {
1185 page_size = 2048;
1186 page_mask = page_size - 1;
1187 }
1188 else
1189 {
1190 page_size = flash_page_size();
1191 page_mask = page_size - 1;
1192 }
1193
Shashank Mittal162244e2011-08-08 19:01:25 -07001194 if(target_use_signed_kernel())
1195 {
1196 read_device_info(&device);
1197
Shashank Mittal162244e2011-08-08 19:01:25 -07001198 }
1199
Greg Griscod6250552011-06-29 14:40:23 -07001200 target_serialno((unsigned char *) sn_buf);
Ajay Dudanib06c05f2011-05-12 14:46:10 -07001201 dprintf(SPEW,"serial number: %s\n",sn_buf);
Subbaraman Narayanamurthyf17b4ae2011-02-16 20:19:56 -08001202 surf_udc_device.serialno = sn_buf;
1203
Chandan Uddaraju2943fd62010-06-21 10:56:39 -07001204 /* Check if we should do something other than booting up */
Shashank Mittald8c42bf2010-06-09 15:44:28 -07001205 if (keys_get_state(KEY_HOME) != 0)
1206 boot_into_recovery = 1;
Wentao Xu153902c2010-12-20 16:20:52 -05001207 if (keys_get_state(KEY_VOLUMEUP) != 0)
1208 boot_into_recovery = 1;
Subbaraman Narayanamurthy0e445b02011-06-19 21:34:46 -07001209 if(!boot_into_recovery)
1210 {
1211 if (keys_get_state(KEY_BACK) != 0)
1212 goto fastboot;
1213 if (keys_get_state(KEY_VOLUMEDOWN) != 0)
1214 goto fastboot;
1215 }
Shashank Mittald8c42bf2010-06-09 15:44:28 -07001216
1217 #if NO_KEYPAD_DRIVER
Kinson Chik0b1c8162011-08-31 16:31:57 -07001218 if (fastboot_trigger())
Shashank Mittald8c42bf2010-06-09 15:44:28 -07001219 goto fastboot;
1220 #endif
Chandan Uddarajubedca152010-06-02 23:05:15 -07001221
Ajay Dudani77421292010-10-27 19:34:06 -07001222 reboot_mode = check_reboot_mode();
1223 if (reboot_mode == RECOVERY_MODE) {
1224 boot_into_recovery = 1;
1225 } else if(reboot_mode == FASTBOOT_MODE) {
1226 goto fastboot;
1227 }
1228
Shashank Mittal23b8f422010-04-16 19:27:21 -07001229 if (target_is_emmc_boot())
Shashank Mittald8c42bf2010-06-09 15:44:28 -07001230 {
Subbaraman Narayanamurthy0e445b02011-06-19 21:34:46 -07001231 if(emmc_recovery_init())
1232 dprintf(ALWAYS,"error in emmc_recovery_init\n");
Shashank Mittala0032282011-08-26 14:50:11 -07001233 if(target_use_signed_kernel())
1234 {
1235 if((device.is_unlocked) || (device.is_tampered))
1236 {
1237 #ifdef TZ_TAMPER_FUSE
1238 set_tamper_fuse_cmd();
1239 #endif
1240 }
1241 }
Shashank Mittald8c42bf2010-06-09 15:44:28 -07001242 boot_linux_from_mmc();
1243 }
1244 else
1245 {
Shashank Mittald8c42bf2010-06-09 15:44:28 -07001246 recovery_init();
1247 boot_linux_from_flash();
1248 }
Dima Zavinb4283602009-01-26 16:36:57 -08001249 dprintf(CRITICAL, "ERROR: Could not do normal boot. Reverting "
1250 "to fastboot mode.\n");
1251
1252fastboot:
Chandan Uddaraju2943fd62010-06-21 10:56:39 -07001253
Shashank Mittal162244e2011-08-08 19:01:25 -07001254 target_fastboot_init();
Amol Jadi57abe4c2011-05-24 15:47:27 -07001255
Shashank Mittald8c42bf2010-06-09 15:44:28 -07001256 if(!usb_init)
1257 udc_init(&surf_udc_device);
Brian Swetland9c4c0752009-01-25 16:23:50 -08001258
1259 fastboot_register("boot", cmd_boot);
Bikas Gurungd48bd242010-09-04 19:54:32 -07001260
Shashank Mittal23b8f422010-04-16 19:27:21 -07001261 if (target_is_emmc_boot())
Shashank Mittald8c42bf2010-06-09 15:44:28 -07001262 {
1263 fastboot_register("flash:", cmd_flash_mmc);
Bikas Gurungd48bd242010-09-04 19:54:32 -07001264 fastboot_register("erase:", cmd_erase_mmc);
Shashank Mittald8c42bf2010-06-09 15:44:28 -07001265 }
1266 else
1267 {
1268 fastboot_register("flash:", cmd_flash);
Bikas Gurungd48bd242010-09-04 19:54:32 -07001269 fastboot_register("erase:", cmd_erase);
Shashank Mittald8c42bf2010-06-09 15:44:28 -07001270 }
1271
1272 fastboot_register("continue", cmd_continue);
Chandan Uddaraju94183c02010-01-15 15:13:59 -08001273 fastboot_register("reboot", cmd_reboot);
1274 fastboot_register("reboot-bootloader", cmd_reboot_bootloader);
Shashank Mittal162244e2011-08-08 19:01:25 -07001275 fastboot_register("oem unlock", cmd_oem_unlock);
Shashank Mittala0032282011-08-26 14:50:11 -07001276 fastboot_register("oem device-info", cmd_oem_devinfo);
Subbaraman Narayanamurthyeb92bcc2010-07-20 14:32:46 -07001277 fastboot_publish("product", TARGET(BOARD));
Brian Swetland9c4c0752009-01-25 16:23:50 -08001278 fastboot_publish("kernel", "lk");
Kinson Chikf1a43512011-07-14 11:28:39 -07001279 partition_dump();
Vivek Mehta5f1c9d42011-04-01 20:11:59 -07001280 sz = target_get_max_flash_size();
1281 fastboot_init(target_get_scratch_address(), sz);
Brian Swetland9c4c0752009-01-25 16:23:50 -08001282 udc_start();
Brian Swetland9c4c0752009-01-25 16:23:50 -08001283}
1284
1285APP_START(aboot)
1286 .init = aboot_init,
1287APP_END
1288