blob: fa80f28f185781d1ba73d9ce7583b06438d2b473 [file] [log] [blame]
Brian Swetland9c4c0752009-01-25 16:23:50 -08001/*
2 * Copyright (c) 2009, Google Inc.
3 * All rights reserved.
4 *
Kuogee Hsiehfb4b5c32013-12-20 08:34:10 -08005 * Copyright (c) 2009-2014, The Linux Foundation. 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.
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -070014 * * Neither the name of The Linux Foundation nor
Chandan Uddaraju5fa471a2009-12-02 17:31:34 -080015 * 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>
Brian Swetland9c4c0752009-01-25 16:23:50 -080036#include <string.h>
Channagoud Kadabi132ff552013-04-19 14:34:44 -070037#include <stdlib.h>
Channagoud Kadabice737c82014-06-18 17:41:01 -070038#include <limits.h>
Brian Swetland9c4c0752009-01-25 16:23:50 -080039#include <kernel/thread.h>
40#include <arch/ops.h>
41
Dima Zavin214cc642009-01-26 11:16:21 -080042#include <dev/flash.h>
43#include <lib/ptable.h>
Dima Zavinb4283602009-01-26 16:36:57 -080044#include <dev/keys.h>
Shashank Mittal4f99a882010-02-01 13:58:50 -080045#include <dev/fbcon.h>
Ajay Dudanid04110c2011-01-17 23:55:07 -080046#include <baseband.h>
Greg Griscod6250552011-06-29 14:40:23 -070047#include <target.h>
48#include <mmc.h>
Kinson Chikf1a43512011-07-14 11:28:39 -070049#include <partition_parser.h>
Greg Griscod6250552011-06-29 14:40:23 -070050#include <platform.h>
Shashank Mittalcd98d472011-08-02 14:29:24 -070051#include <crypto_hash.h>
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -070052#include <malloc.h>
Amol Jadi492d5a52013-03-15 16:12:34 -070053#include <boot_stats.h>
Amir Samuelov57a6fa22013-06-05 16:36:43 +030054#include <sha.h>
Dima Zavin214cc642009-01-26 11:16:21 -080055
Neeti Desai17379b82012-06-04 18:42:53 -070056#if DEVICE_TREE
57#include <libfdt.h>
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -070058#include <dev_tree.h>
Neeti Desai17379b82012-06-04 18:42:53 -070059#endif
60
Shashank Mittalcd98d472011-08-02 14:29:24 -070061#include "image_verify.h"
Shashank Mittal024c0332010-02-03 11:44:00 -080062#include "recovery.h"
Brian Swetland9c4c0752009-01-25 16:23:50 -080063#include "bootimg.h"
64#include "fastboot.h"
Ajay Dudani5c761132011-04-07 20:19:04 -070065#include "sparse_format.h"
Greg Grisco6e754772011-06-23 12:19:39 -070066#include "mmc.h"
Shashank Mittal162244e2011-08-08 19:01:25 -070067#include "devinfo.h"
Neeti Desai465491e2012-07-31 12:53:35 -070068#include "board.h"
Shashank Mittal162244e2011-08-08 19:01:25 -070069#include "scm.h"
kchik@codeaurora.orgbce18ea2011-04-18 20:22:28 -070070
Sridhar Parasuram78344412015-08-29 11:13:07 -070071#if VERIFIED_BOOT
72#include "boot_verifier.h"
73#include "secapp_loader.h"
74#endif
75
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -070076extern bool target_use_signed_kernel(void);
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -070077extern void platform_uninit(void);
Channagoud Kadabi33defe22013-06-18 18:35:40 -070078extern void target_uninit(void);
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -070079
80void write_device_info_mmc(device_info *dev);
81void write_device_info_flash(device_info *dev);
82
Sridhar Parasuram901bb702014-10-24 14:06:03 -070083/* fastboot command function pointer */
84typedef void (*fastboot_cmd_fn) (const char *, void *, unsigned);
85
86struct fastboot_cmd_desc {
87 char * name;
88 fastboot_cmd_fn cb;
89};
90
Subbaraman Narayanamurthyeb92bcc2010-07-20 14:32:46 -070091#define EXPAND(NAME) #NAME
92#define TARGET(NAME) EXPAND(NAME)
Brian Swetland2defe162009-08-18 14:35:59 -070093
Ajay Dudanicd01f9b2010-02-23 21:13:04 -080094#ifdef MEMBASE
95#define EMMC_BOOT_IMG_HEADER_ADDR (0xFF000+(MEMBASE))
96#else
David Ng183a7422009-12-07 14:55:21 -080097#define EMMC_BOOT_IMG_HEADER_ADDR 0xFF000
Ajay Dudanicd01f9b2010-02-23 21:13:04 -080098#endif
99
Deepa Dinamani0e163a42013-05-24 17:08:15 -0700100#ifndef MEMSIZE
101#define MEMSIZE 1024*1024
102#endif
103
104#define MAX_TAGS_SIZE 1024
105
Chandan Uddarajude85d3f2010-01-05 16:32:33 -0800106#define RECOVERY_MODE 0x77665502
107#define FASTBOOT_MODE 0x77665500
108
Sridhar Parasuram78344412015-08-29 11:13:07 -0700109#if VERIFIED_BOOT
110#define DM_VERITY_LOGGING 0x77665508
111#define DM_VERITY_ENFORCING 0x77665509
112#define DM_VERITY_KEYSCLEAR 0x7766550A
113#endif
114
Kun Liang2f1601a2013-08-12 16:29:54 +0800115/* make 4096 as default size to ensure EFS,EXT4's erasing */
116#define DEFAULT_ERASE_SIZE 4096
Kuogee Hsiehfb4b5c32013-12-20 08:34:10 -0800117#define MAX_PANEL_BUF_SIZE 128
Kun Liang2f1601a2013-08-12 16:29:54 +0800118
Channagoud Kadabice737c82014-06-18 17:41:01 -0700119#define ADD_OF(a, b) (UINT_MAX - b > a) ? (a + b) : UINT_MAX
120
David Ng183a7422009-12-07 14:55:21 -0800121static const char *emmc_cmdline = " androidboot.emmc=true";
Subbaraman Narayanamurthyf17b4ae2011-02-16 20:19:56 -0800122static const char *usb_sn_cmdline = " androidboot.serialno=";
Pavel Nedev328ac822013-04-05 15:25:11 +0300123static const char *androidboot_mode = " androidboot.mode=";
Dhaval Patel223ec952013-07-18 14:49:44 -0700124static const char *display_cmdline = " mdss_mdp.panel=";
Pavel Nedev898298c2013-02-27 12:36:09 -0800125static const char *loglevel = " quiet";
Ajay Dudanica3a33c2011-11-18 08:31:40 -0800126static const char *battchg_pause = " androidboot.mode=charger";
Shashank Mittalcd98d472011-08-02 14:29:24 -0700127static const char *auth_kernel = " androidboot.authorized_kernel=true";
Pavel Nedev5614d222013-06-17 18:01:02 +0300128static const char *secondary_gpt_enable = " gpt";
David Ng183a7422009-12-07 14:55:21 -0800129
Ajay Dudani6cff85e2011-02-04 16:02:16 -0800130static const char *baseband_apq = " androidboot.baseband=apq";
131static const char *baseband_msm = " androidboot.baseband=msm";
132static const char *baseband_csfb = " androidboot.baseband=csfb";
133static const char *baseband_svlte2a = " androidboot.baseband=svlte2a";
Ajay Dudani403bc492011-09-30 16:17:21 -0700134static const char *baseband_mdm = " androidboot.baseband=mdm";
Amol Jadi5c61a952012-05-04 17:05:35 -0700135static const char *baseband_sglte = " androidboot.baseband=sglte";
Amol Jadi2a15a272013-01-22 12:03:36 -0800136static const char *baseband_dsda = " androidboot.baseband=dsda";
137static const char *baseband_dsda2 = " androidboot.baseband=dsda2";
sundarajan srinivasanf8e9f3f2013-03-04 15:56:58 -0800138static const char *baseband_sglte2 = " androidboot.baseband=sglte2";
Ajay Dudanid04110c2011-01-17 23:55:07 -0800139
Sridhar Parasuram78344412015-08-29 11:13:07 -0700140#if VERIFIED_BOOT
141static const char *verity_mode = " androidboot.veritymode=";
142static const char *verified_state= " androidboot.verifiedbootstate=";
143
144//indexed based on enum values, green is 0 by default
145
146struct verified_boot_verity_mode vbvm[] =
147{
148 {false, "logging"},
149 {true, "enforcing"},
150};
151struct verified_boot_state_name vbsn[] =
152{
153 {GREEN, "green"},
154 {ORANGE, "orange"},
155 {YELLOW,"yellow"},
156 {RED,"red" },
157};
158#endif
159
Deepa Dinamani41fa8d62013-05-23 13:25:36 -0700160static unsigned page_size = 0;
161static unsigned page_mask = 0;
162static char ffbm_mode_string[FFBM_MODE_BUF_SIZE];
163static bool boot_into_ffbm;
164
Shashank Mittalcd98d472011-08-02 14:29:24 -0700165/* Assuming unauthorized kernel image by default */
166static int auth_kernel_img = 0;
167
Sridhar Parasuram78344412015-08-29 11:13:07 -0700168#if VERIFIED_BOOT
169static device_info device = {DEVICE_MAGIC, 0, 0, 0, 0, 1};
170#else
Unnati Gandhi15d08f92014-01-24 11:01:01 +0530171static device_info device = {DEVICE_MAGIC, 0, 0, 0, 0};
Sridhar Parasuram78344412015-08-29 11:13:07 -0700172#endif
Shashank Mittal162244e2011-08-08 19:01:25 -0700173
Dima Zavin42168f22009-01-30 11:52:22 -0800174struct atag_ptbl_entry
175{
176 char name[16];
177 unsigned offset;
178 unsigned size;
179 unsigned flags;
180};
181
Channagoud Kadabi4c4884e2013-04-09 17:12:13 -0700182/*
183 * Partition info, required to be published
184 * for fastboot
185 */
186struct getvar_partition_info {
187 const char part_name[MAX_GPT_NAME_SIZE]; /* Partition name */
188 char getvar_size[MAX_GET_VAR_NAME_SIZE]; /* fastboot get var name for size */
189 char getvar_type[MAX_GET_VAR_NAME_SIZE]; /* fastboot get var name for type */
190 char size_response[MAX_RSP_SIZE]; /* fastboot response for size */
191 char type_response[MAX_RSP_SIZE]; /* fastboot response for type */
192};
193
194/*
195 * Right now, we are publishing the info for only
196 * three partitions
197 */
198struct getvar_partition_info part_info[] =
199{
200 { "system" , "partition-size:", "partition-type:", "", "ext4" },
201 { "userdata", "partition-size:", "partition-type:", "", "ext4" },
202 { "cache" , "partition-size:", "partition-type:", "", "ext4" },
203};
204
205char max_download_size[MAX_RSP_SIZE];
Ameya Thakur11cf1a62013-08-05 12:44:48 -0700206char charger_screen_enabled[MAX_RSP_SIZE];
Subbaraman Narayanamurthyf17b4ae2011-02-16 20:19:56 -0800207char sn_buf[13];
Dhaval Patel223ec952013-07-18 14:49:44 -0700208char display_panel_buf[MAX_PANEL_BUF_SIZE];
Unnati Gandhi15d08f92014-01-24 11:01:01 +0530209char panel_display_mode[MAX_RSP_SIZE];
Greg Griscod6250552011-06-29 14:40:23 -0700210
Greg Griscod2471ef2011-07-14 13:00:42 -0700211extern int emmc_recovery_init(void);
212
Kinson Chik0b1c8162011-08-31 16:31:57 -0700213#if NO_KEYPAD_DRIVER
214extern int fastboot_trigger(void);
215#endif
Greg Griscod2471ef2011-07-14 13:00:42 -0700216
Channagoud Kadabia22144f2013-03-20 11:49:01 -0700217static void update_ker_tags_rdisk_addr(struct boot_img_hdr *hdr)
218{
219 /* overwrite the destination of specified for the project */
Channagoud Kadabi7042fa32013-04-26 16:44:14 -0700220#ifdef ABOOT_IGNORE_BOOT_HEADER_ADDRS
221 hdr->kernel_addr = ABOOT_FORCE_KERNEL_ADDR;
222 hdr->ramdisk_addr = ABOOT_FORCE_RAMDISK_ADDR;
223 hdr->tags_addr = ABOOT_FORCE_TAGS_ADDR;
Channagoud Kadabia22144f2013-03-20 11:49:01 -0700224#endif
225}
226
Dima Zavin42168f22009-01-30 11:52:22 -0800227static void ptentry_to_tag(unsigned **ptr, struct ptentry *ptn)
228{
229 struct atag_ptbl_entry atag_ptn;
230
231 memcpy(atag_ptn.name, ptn->name, 16);
232 atag_ptn.name[15] = '\0';
233 atag_ptn.offset = ptn->start;
234 atag_ptn.size = ptn->length;
235 atag_ptn.flags = ptn->flags;
236 memcpy(*ptr, &atag_ptn, sizeof(struct atag_ptbl_entry));
237 *ptr += sizeof(struct atag_ptbl_entry) / sizeof(unsigned);
238}
Brian Swetland9c4c0752009-01-25 16:23:50 -0800239
Neeti Desaie245d492012-06-01 12:52:13 -0700240unsigned char *update_cmdline(const char * cmdline)
Brian Swetland9c4c0752009-01-25 16:23:50 -0800241{
David Ng183a7422009-12-07 14:55:21 -0800242 int cmdline_len = 0;
243 int have_cmdline = 0;
Amol Jadi168b7712012-03-06 16:15:00 -0800244 unsigned char *cmdline_final = NULL;
Neeti Desaie245d492012-06-01 12:52:13 -0700245 int pause_at_bootup = 0;
Pavel Nedev5614d222013-06-17 18:01:02 +0300246 bool gpt_exists = partition_gpt_exists();
Sridhar Parasuram78344412015-08-29 11:13:07 -0700247#if VERIFIED_BOOT
248 uint32_t boot_state = boot_verify_get_state();
249#endif
250
Dima Zavin42168f22009-01-30 11:52:22 -0800251
Brian Swetland9c4c0752009-01-25 16:23:50 -0800252 if (cmdline && cmdline[0]) {
David Ng183a7422009-12-07 14:55:21 -0800253 cmdline_len = strlen(cmdline);
254 have_cmdline = 1;
255 }
256 if (target_is_emmc_boot()) {
257 cmdline_len += strlen(emmc_cmdline);
258 }
Subbaraman Narayanamurthyf17b4ae2011-02-16 20:19:56 -0800259
260 cmdline_len += strlen(usb_sn_cmdline);
261 cmdline_len += strlen(sn_buf);
262
Sridhar Parasuram78344412015-08-29 11:13:07 -0700263#if VERIFIED_BOOT
264 cmdline_len += strlen(verified_state) + strlen(vbsn[boot_state].name);
265 cmdline_len += strlen(verity_mode) + strlen(vbvm[device.verity_mode].name);
266#endif
267
268
Pavel Nedev5614d222013-06-17 18:01:02 +0300269 if (boot_into_recovery && gpt_exists)
270 cmdline_len += strlen(secondary_gpt_enable);
271
Pavel Nedev328ac822013-04-05 15:25:11 +0300272 if (boot_into_ffbm) {
273 cmdline_len += strlen(androidboot_mode);
Deepa Dinamani41fa8d62013-05-23 13:25:36 -0700274 cmdline_len += strlen(ffbm_mode_string);
Pavel Nedev898298c2013-02-27 12:36:09 -0800275 /* reduce kernel console messages to speed-up boot */
276 cmdline_len += strlen(loglevel);
Ameya Thakur11cf1a62013-08-05 12:44:48 -0700277 } else if (device.charger_screen_enabled &&
278 target_pause_for_battery_charge()) {
David Ngf773dde2010-07-26 19:55:08 -0700279 pause_at_bootup = 1;
280 cmdline_len += strlen(battchg_pause);
281 }
Ajay Dudanid04110c2011-01-17 23:55:07 -0800282
Shashank Mittalcd98d472011-08-02 14:29:24 -0700283 if(target_use_signed_kernel() && auth_kernel_img) {
284 cmdline_len += strlen(auth_kernel);
285 }
286
Ajay Dudanid04110c2011-01-17 23:55:07 -0800287 /* Determine correct androidboot.baseband to use */
288 switch(target_baseband())
289 {
290 case BASEBAND_APQ:
291 cmdline_len += strlen(baseband_apq);
292 break;
293
294 case BASEBAND_MSM:
295 cmdline_len += strlen(baseband_msm);
296 break;
297
298 case BASEBAND_CSFB:
299 cmdline_len += strlen(baseband_csfb);
300 break;
301
Ajay Dudani6cff85e2011-02-04 16:02:16 -0800302 case BASEBAND_SVLTE2A:
303 cmdline_len += strlen(baseband_svlte2a);
Ajay Dudanid04110c2011-01-17 23:55:07 -0800304 break;
Ajay Dudani403bc492011-09-30 16:17:21 -0700305
306 case BASEBAND_MDM:
307 cmdline_len += strlen(baseband_mdm);
308 break;
Amol Jadi5c61a952012-05-04 17:05:35 -0700309
310 case BASEBAND_SGLTE:
311 cmdline_len += strlen(baseband_sglte);
312 break;
Channagoud Kadabi141f2982012-10-31 11:23:02 +0530313
sundarajan srinivasanf8e9f3f2013-03-04 15:56:58 -0800314 case BASEBAND_SGLTE2:
315 cmdline_len += strlen(baseband_sglte2);
316 break;
317
Channagoud Kadabi141f2982012-10-31 11:23:02 +0530318 case BASEBAND_DSDA:
319 cmdline_len += strlen(baseband_dsda);
320 break;
Amol Jadi2a15a272013-01-22 12:03:36 -0800321
322 case BASEBAND_DSDA2:
323 cmdline_len += strlen(baseband_dsda2);
324 break;
Ajay Dudanid04110c2011-01-17 23:55:07 -0800325 }
326
Dhaval Patel223ec952013-07-18 14:49:44 -0700327 if (target_display_panel_node(display_panel_buf, MAX_PANEL_BUF_SIZE) &&
328 strlen(display_panel_buf))
329 {
330 cmdline_len += strlen(display_cmdline);
331 cmdline_len += strlen(display_panel_buf);
332 }
333
David Ng183a7422009-12-07 14:55:21 -0800334 if (cmdline_len > 0) {
335 const char *src;
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -0700336 unsigned char *dst = (unsigned char*) malloc((cmdline_len + 4) & (~3));
337 ASSERT(dst != NULL);
Neeti Desaie245d492012-06-01 12:52:13 -0700338
Amol Jadi168b7712012-03-06 16:15:00 -0800339 /* Save start ptr for debug print */
Neeti Desaie245d492012-06-01 12:52:13 -0700340 cmdline_final = dst;
David Ng183a7422009-12-07 14:55:21 -0800341 if (have_cmdline) {
342 src = cmdline;
343 while ((*dst++ = *src++));
344 }
345 if (target_is_emmc_boot()) {
346 src = emmc_cmdline;
347 if (have_cmdline) --dst;
David Ngf773dde2010-07-26 19:55:08 -0700348 have_cmdline = 1;
349 while ((*dst++ = *src++));
350 }
Sridhar Parasuram78344412015-08-29 11:13:07 -0700351#if VERIFIED_BOOT
352 src = verified_state;
353 if(have_cmdline) --dst;
354 have_cmdline = 1;
355 while ((*dst++ = *src++));
356 src = vbsn[boot_state].name;
357 if(have_cmdline) --dst;
358 while ((*dst++ = *src++));
Subbaraman Narayanamurthyf17b4ae2011-02-16 20:19:56 -0800359
Sridhar Parasuram78344412015-08-29 11:13:07 -0700360 src = verity_mode;
361 if(have_cmdline) --dst;
362 while ((*dst++ = *src++));
363 src = vbvm[device.verity_mode].name;
364 if(have_cmdline) -- dst;
365 while ((*dst++ = *src++));
366#endif
Subbaraman Narayanamurthyf17b4ae2011-02-16 20:19:56 -0800367 src = usb_sn_cmdline;
368 if (have_cmdline) --dst;
369 have_cmdline = 1;
370 while ((*dst++ = *src++));
371 src = sn_buf;
372 if (have_cmdline) --dst;
373 have_cmdline = 1;
374 while ((*dst++ = *src++));
375
Pavel Nedev5614d222013-06-17 18:01:02 +0300376 if (boot_into_recovery && gpt_exists) {
377 src = secondary_gpt_enable;
378 if (have_cmdline) --dst;
379 while ((*dst++ = *src++));
380 }
381
Pavel Nedev328ac822013-04-05 15:25:11 +0300382 if (boot_into_ffbm) {
383 src = androidboot_mode;
384 if (have_cmdline) --dst;
385 while ((*dst++ = *src++));
Deepa Dinamani41fa8d62013-05-23 13:25:36 -0700386 src = ffbm_mode_string;
Pavel Nedev328ac822013-04-05 15:25:11 +0300387 if (have_cmdline) --dst;
388 while ((*dst++ = *src++));
Pavel Nedev898298c2013-02-27 12:36:09 -0800389 src = loglevel;
390 if (have_cmdline) --dst;
391 while ((*dst++ = *src++));
Pavel Nedev328ac822013-04-05 15:25:11 +0300392 } else if (pause_at_bootup) {
David Ngf773dde2010-07-26 19:55:08 -0700393 src = battchg_pause;
394 if (have_cmdline) --dst;
David Ng183a7422009-12-07 14:55:21 -0800395 while ((*dst++ = *src++));
396 }
Ajay Dudanid04110c2011-01-17 23:55:07 -0800397
Shashank Mittalcd98d472011-08-02 14:29:24 -0700398 if(target_use_signed_kernel() && auth_kernel_img) {
399 src = auth_kernel;
400 if (have_cmdline) --dst;
401 while ((*dst++ = *src++));
402 }
403
Ajay Dudanid04110c2011-01-17 23:55:07 -0800404 switch(target_baseband())
405 {
406 case BASEBAND_APQ:
407 src = baseband_apq;
408 if (have_cmdline) --dst;
409 while ((*dst++ = *src++));
410 break;
411
412 case BASEBAND_MSM:
413 src = baseband_msm;
414 if (have_cmdline) --dst;
415 while ((*dst++ = *src++));
416 break;
417
418 case BASEBAND_CSFB:
419 src = baseband_csfb;
420 if (have_cmdline) --dst;
421 while ((*dst++ = *src++));
422 break;
423
Ajay Dudani6cff85e2011-02-04 16:02:16 -0800424 case BASEBAND_SVLTE2A:
425 src = baseband_svlte2a;
Ajay Dudanid04110c2011-01-17 23:55:07 -0800426 if (have_cmdline) --dst;
427 while ((*dst++ = *src++));
428 break;
Ajay Dudani403bc492011-09-30 16:17:21 -0700429
430 case BASEBAND_MDM:
431 src = baseband_mdm;
432 if (have_cmdline) --dst;
433 while ((*dst++ = *src++));
434 break;
Amol Jadi5c61a952012-05-04 17:05:35 -0700435
436 case BASEBAND_SGLTE:
437 src = baseband_sglte;
438 if (have_cmdline) --dst;
439 while ((*dst++ = *src++));
440 break;
Channagoud Kadabi141f2982012-10-31 11:23:02 +0530441
sundarajan srinivasanf8e9f3f2013-03-04 15:56:58 -0800442 case BASEBAND_SGLTE2:
443 src = baseband_sglte2;
444 if (have_cmdline) --dst;
445 while ((*dst++ = *src++));
446 break;
447
Channagoud Kadabi141f2982012-10-31 11:23:02 +0530448 case BASEBAND_DSDA:
449 src = baseband_dsda;
450 if (have_cmdline) --dst;
451 while ((*dst++ = *src++));
452 break;
Amol Jadi2a15a272013-01-22 12:03:36 -0800453
454 case BASEBAND_DSDA2:
455 src = baseband_dsda2;
456 if (have_cmdline) --dst;
457 while ((*dst++ = *src++));
458 break;
Ajay Dudanid04110c2011-01-17 23:55:07 -0800459 }
Dhaval Patel223ec952013-07-18 14:49:44 -0700460
461 if (strlen(display_panel_buf)) {
462 src = display_cmdline;
463 if (have_cmdline) --dst;
464 while ((*dst++ = *src++));
465 src = display_panel_buf;
466 if (have_cmdline) --dst;
467 while ((*dst++ = *src++));
468 }
Neeti Desaie245d492012-06-01 12:52:13 -0700469 }
Dhaval Patel223ec952013-07-18 14:49:44 -0700470
471
Deepa Dinamani8b8736d2012-12-19 15:00:56 -0800472 dprintf(INFO, "cmdline: %s\n", cmdline_final);
Neeti Desaie245d492012-06-01 12:52:13 -0700473 return cmdline_final;
474}
475
476unsigned *atag_core(unsigned *ptr)
477{
478 /* CORE */
479 *ptr++ = 2;
480 *ptr++ = 0x54410001;
481
482 return ptr;
483
484}
485
486unsigned *atag_ramdisk(unsigned *ptr, void *ramdisk,
487 unsigned ramdisk_size)
488{
489 if (ramdisk_size) {
490 *ptr++ = 4;
491 *ptr++ = 0x54420005;
492 *ptr++ = (unsigned)ramdisk;
493 *ptr++ = ramdisk_size;
Brian Swetland9c4c0752009-01-25 16:23:50 -0800494 }
495
Neeti Desaie245d492012-06-01 12:52:13 -0700496 return ptr;
497}
498
499unsigned *atag_ptable(unsigned **ptr_addr)
500{
501 int i;
502 struct ptable *ptable;
503
504 if ((ptable = flash_get_ptable()) && (ptable->count != 0)) {
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -0700505 *(*ptr_addr)++ = 2 + (ptable->count * (sizeof(struct atag_ptbl_entry) /
506 sizeof(unsigned)));
Neeti Desaie245d492012-06-01 12:52:13 -0700507 *(*ptr_addr)++ = 0x4d534d70;
508 for (i = 0; i < ptable->count; ++i)
509 ptentry_to_tag(ptr_addr, ptable_get(ptable, i));
510 }
511
512 return (*ptr_addr);
513}
514
515unsigned *atag_cmdline(unsigned *ptr, const char *cmdline)
516{
517 int cmdline_length = 0;
518 int n;
Neeti Desaie245d492012-06-01 12:52:13 -0700519 char *dest;
520
Amol Jadi10c7d1c2013-01-25 13:24:29 -0800521 cmdline_length = strlen((const char*)cmdline);
Neeti Desaie245d492012-06-01 12:52:13 -0700522 n = (cmdline_length + 4) & (~3);
523
524 *ptr++ = (n / 4) + 2;
525 *ptr++ = 0x54410009;
526 dest = (char *) ptr;
Amol Jadi10c7d1c2013-01-25 13:24:29 -0800527 while ((*dest++ = *cmdline++));
Neeti Desaie245d492012-06-01 12:52:13 -0700528 ptr += (n / 4);
529
530 return ptr;
531}
532
533unsigned *atag_end(unsigned *ptr)
534{
Brian Swetland9c4c0752009-01-25 16:23:50 -0800535 /* END */
536 *ptr++ = 0;
537 *ptr++ = 0;
538
Neeti Desaie245d492012-06-01 12:52:13 -0700539 return ptr;
540}
541
542void generate_atags(unsigned *ptr, const char *cmdline,
543 void *ramdisk, unsigned ramdisk_size)
544{
545
546 ptr = atag_core(ptr);
547 ptr = atag_ramdisk(ptr, ramdisk, ramdisk_size);
548 ptr = target_atag_mem(ptr);
549
550 /* Skip NAND partition ATAGS for eMMC boot */
551 if (!target_is_emmc_boot()){
552 ptr = atag_ptable(&ptr);
553 }
554
555 ptr = atag_cmdline(ptr, cmdline);
556 ptr = atag_end(ptr);
557}
558
Deepa Dinamani0bf2f442012-10-19 11:41:06 -0700559typedef void entry_func_ptr(unsigned, unsigned, unsigned*);
Neeti Desaie245d492012-06-01 12:52:13 -0700560void boot_linux(void *kernel, unsigned *tags,
561 const char *cmdline, unsigned machtype,
562 void *ramdisk, unsigned ramdisk_size)
563{
Amol Jadi10c7d1c2013-01-25 13:24:29 -0800564 unsigned char *final_cmdline;
Amol Jadib6be5c12012-11-14 13:39:51 -0800565#if DEVICE_TREE
Neeti Desai17379b82012-06-04 18:42:53 -0700566 int ret = 0;
Amol Jadib6be5c12012-11-14 13:39:51 -0800567#endif
568
Deepa Dinamani0bf2f442012-10-19 11:41:06 -0700569 void (*entry)(unsigned, unsigned, unsigned*) = (entry_func_ptr*)(PA((addr_t)kernel));
Deepa Dinamani25a9f762012-11-30 15:57:15 -0800570 uint32_t tags_phys = PA((addr_t)tags);
571
572 ramdisk = PA(ramdisk);
Neeti Desaie245d492012-06-01 12:52:13 -0700573
Amol Jadi10c7d1c2013-01-25 13:24:29 -0800574 final_cmdline = update_cmdline((const char*)cmdline);
575
Neeti Desai17379b82012-06-04 18:42:53 -0700576#if DEVICE_TREE
Amol Jadib6be5c12012-11-14 13:39:51 -0800577 dprintf(INFO, "Updating device tree: start\n");
578
Neeti Desai17379b82012-06-04 18:42:53 -0700579 /* Update the Device Tree */
Amol Jadi10c7d1c2013-01-25 13:24:29 -0800580 ret = update_device_tree((void *)tags, final_cmdline, ramdisk, ramdisk_size);
Neeti Desai17379b82012-06-04 18:42:53 -0700581 if(ret)
582 {
583 dprintf(CRITICAL, "ERROR: Updating Device Tree Failed \n");
584 ASSERT(0);
585 }
Amol Jadib6be5c12012-11-14 13:39:51 -0800586 dprintf(INFO, "Updating device tree: done\n");
Neeti Desai17379b82012-06-04 18:42:53 -0700587#else
Neeti Desaie245d492012-06-01 12:52:13 -0700588 /* Generating the Atags */
Amol Jadi10c7d1c2013-01-25 13:24:29 -0800589 generate_atags(tags, final_cmdline, ramdisk, ramdisk_size);
Neeti Desai17379b82012-06-04 18:42:53 -0700590#endif
Neeti Desaie245d492012-06-01 12:52:13 -0700591
Channagoud Kadabi33defe22013-06-18 18:35:40 -0700592 /* Perform target specific cleanup */
593 target_uninit();
594
Aravind Venkateswarandb0d5262014-02-25 16:25:30 -0800595 /* Turn off splash screen if enabled */
596#if DISPLAY_SPLASH_SCREEN
597 target_display_shutdown();
598#endif
599
600
Deepa Dinamani33734bc2013-03-06 12:16:06 -0800601 dprintf(INFO, "booting linux @ %p, ramdisk @ %p (%d), tags/device tree @ %p\n",
602 entry, ramdisk, ramdisk_size, tags_phys);
Brian Swetland9c4c0752009-01-25 16:23:50 -0800603
604 enter_critical_section();
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -0700605
Amol Jadi4421e652011-06-16 15:00:48 -0700606 /* do any platform specific cleanup before kernel entry */
607 platform_uninit();
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -0700608
Brian Swetland9c4c0752009-01-25 16:23:50 -0800609 arch_disable_cache(UCACHE);
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -0700610
Amol Jadi504f9fe2012-08-16 13:56:48 -0700611#if ARM_WITH_MMU
Brian Swetland9c4c0752009-01-25 16:23:50 -0800612 arch_disable_mmu();
Amol Jadi504f9fe2012-08-16 13:56:48 -0700613#endif
Amol Jadi492d5a52013-03-15 16:12:34 -0700614 bs_set_timestamp(BS_KERNEL_ENTRY);
Deepa Dinamani0bf2f442012-10-19 11:41:06 -0700615 entry(0, machtype, (unsigned*)tags_phys);
Brian Swetland9c4c0752009-01-25 16:23:50 -0800616}
617
Deepa Dinamani0e163a42013-05-24 17:08:15 -0700618/* Function to check if the memory address range falls within the aboot
619 * boundaries.
620 * start: Start of the memory region
621 * size: Size of the memory region
622 */
623int check_aboot_addr_range_overlap(uint32_t start, uint32_t size)
624{
625 /* Check for boundary conditions. */
Sundarajan Srinivasan74252482013-12-16 17:02:56 -0800626 if ((UINT_MAX - start) < size)
Deepa Dinamani0e163a42013-05-24 17:08:15 -0700627 return -1;
628
629 /* Check for memory overlap. */
630 if ((start < MEMBASE) && ((start + size) <= MEMBASE))
631 return 0;
Channagoud Kadabib4413fd2013-10-15 12:53:52 -0700632 else if (start >= (MEMBASE + MEMSIZE))
Deepa Dinamani0e163a42013-05-24 17:08:15 -0700633 return 0;
634 else
635 return -1;
636}
637
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800638#define ROUND_TO_PAGE(x,y) (((x) + (y)) & (~(y)))
Brian Swetland9c4c0752009-01-25 16:23:50 -0800639
Channagoud Kadabi132ff552013-04-19 14:34:44 -0700640BUF_DMA_ALIGN(buf, 4096); //Equal to max-supported pagesize
Amol Jadib6be5c12012-11-14 13:39:51 -0800641#if DEVICE_TREE
Channagoud Kadabi132ff552013-04-19 14:34:44 -0700642BUF_DMA_ALIGN(dt_buf, 4096);
Amol Jadib6be5c12012-11-14 13:39:51 -0800643#endif
Dima Zavin214cc642009-01-26 11:16:21 -0800644
Deepa Dinamani0e163a42013-05-24 17:08:15 -0700645static void verify_signed_bootimg(uint32_t bootimg_addr, uint32_t bootimg_size)
646{
647 int ret;
Sridhar Parasuram78344412015-08-29 11:13:07 -0700648#if !VERIFIED_BOOT
649#if IMAGE_VERIF_ALGO_SHA1
650 uint32_t auth_algo = CRYPTO_AUTH_ALG_SHA1;
651#else
652 uint32_t auth_algo = CRYPTO_AUTH_ALG_SHA256;
653#endif
654#endif
Deepa Dinamani0e163a42013-05-24 17:08:15 -0700655
656 /* Assume device is rooted at this time. */
657 device.is_tampered = 1;
658
659 dprintf(INFO, "Authenticating boot image (%d): start\n", bootimg_size);
Sridhar Parasuram78344412015-08-29 11:13:07 -0700660#if VERIFIED_BOOT
661 if(boot_into_recovery)
662 {
663 ret = boot_verify_image((unsigned char *)bootimg_addr,
664 bootimg_size, "/recovery");
665 }
666 else
667 {
668 ret = boot_verify_image((unsigned char *)bootimg_addr,
669 bootimg_size, "/boot");
670 }
671 boot_verify_print_state();
672#else
Deepa Dinamani0e163a42013-05-24 17:08:15 -0700673 ret = image_verify((unsigned char *)bootimg_addr,
674 (unsigned char *)(bootimg_addr + bootimg_size),
675 bootimg_size,
676 CRYPTO_AUTH_ALG_SHA256);
Sridhar Parasuram78344412015-08-29 11:13:07 -0700677#endif
Deepa Dinamani0e163a42013-05-24 17:08:15 -0700678 dprintf(INFO, "Authenticating boot image: done return value = %d\n", ret);
679
680 if (ret)
681 {
682 /* Authorized kernel */
683 device.is_tampered = 0;
684 }
685
686#if USE_PCOM_SECBOOT
687 set_tamper_flag(device.is_tampered);
688#endif
Sridhar Parasuram78344412015-08-29 11:13:07 -0700689#if VERIFIED_BOOT
690 switch(boot_verify_get_state())
691 {
692 case RED:
693 dprintf(CRITICAL,
694 "Your device has failed verification and may not work properly.\nWait for 5 seconds before proceeding\n");
695 mdelay(5000);
696 break;
697 case YELLOW:
698 dprintf(CRITICAL,
699 "Your device has loaded a different operating system.\nWait for 5 seconds before proceeding\n");
700 mdelay(5000);
701 break;
702 default:
703 break;
704 }
705#endif
706#if !VERIFIED_BOOT
Deepa Dinamani0e163a42013-05-24 17:08:15 -0700707 if(device.is_tampered)
708 {
709 write_device_info_mmc(&device);
710 #ifdef TZ_TAMPER_FUSE
711 set_tamper_fuse_cmd();
712 #endif
713 #ifdef ASSERT_ON_TAMPER
714 dprintf(CRITICAL, "Device is tampered. Asserting..\n");
715 ASSERT(0);
716 #endif
717 }
Sridhar Parasuram78344412015-08-29 11:13:07 -0700718#endif
Deepa Dinamani0e163a42013-05-24 17:08:15 -0700719}
720
Maunik Shah78a85e52014-03-02 17:47:58 +0530721static bool check_format_bit()
722{
723 bool ret = false;
724 int index;
725 uint64_t offset;
726 struct boot_selection_info *in = NULL;
727 char *buf = NULL;
728
729 index = partition_get_index("bootselect");
730 if (index == INVALID_PTN)
731 {
732 dprintf(INFO, "Unable to locate /bootselect partition\n");
733 return ret;
734 }
735 offset = partition_get_offset(index);
736 if(!offset)
737 {
738 dprintf(INFO, "partition /bootselect doesn't exist\n");
739 return ret;
740 }
741 buf = (char *) memalign(CACHE_LINE, ROUNDUP(page_size, CACHE_LINE));
742 ASSERT(buf);
743 if (mmc_read(offset, (unsigned int *)buf, page_size))
744 {
745 dprintf(INFO, "mmc read failure /bootselect %d\n", page_size);
746 free(buf);
747 return ret;
748 }
749 in = (struct boot_selection_info *) buf;
750 if ((in->signature == BOOTSELECT_SIGNATURE) &&
751 (in->version == BOOTSELECT_VERSION)) {
752 if ((in->state_info & BOOTSELECT_FORMAT) &&
753 !(in->state_info & BOOTSELECT_FACTORY))
754 ret = true;
755 } else {
756 dprintf(CRITICAL, "Signature: 0x%08x or version: 0x%08x mismatched of /bootselect\n",
757 in->signature, in->version);
758 ASSERT(0);
759 }
760 free(buf);
761 return ret;
762}
Sridhar Parasuram78344412015-08-29 11:13:07 -0700763#if VERIFIED_BOOT
764void boot_verifier_init()
765{
766 uint32_t boot_state;
767 /* Check if device unlock */
768 if(device.is_unlocked)
769 {
770 boot_verify_send_event(DEV_UNLOCK);
771 boot_verify_print_state();
772 dprintf(CRITICAL, "Device is unlocked! Skipping verification...\n");
773 return;
774 }
775 else
776 {
777 boot_verify_send_event(BOOT_INIT);
778 }
779
780 /* Initialize keystore */
781 boot_state = boot_verify_keystore_init();
782}
783#endif
Maunik Shah78a85e52014-03-02 17:47:58 +0530784
Shashank Mittal23b8f422010-04-16 19:27:21 -0700785int boot_linux_from_mmc(void)
786{
787 struct boot_img_hdr *hdr = (void*) buf;
788 struct boot_img_hdr *uhdr;
789 unsigned offset = 0;
Deepa Dinamani41fa8d62013-05-23 13:25:36 -0700790 int rcode;
Shashank Mittal23b8f422010-04-16 19:27:21 -0700791 unsigned long long ptn = 0;
Kinson Chikf1a43512011-07-14 11:28:39 -0700792 int index = INVALID_PTN;
Shashank Mittal23b8f422010-04-16 19:27:21 -0700793
Shashank Mittalcd98d472011-08-02 14:29:24 -0700794 unsigned char *image_addr = 0;
795 unsigned kernel_actual;
796 unsigned ramdisk_actual;
797 unsigned imagesize_actual;
Neeti Desai465491e2012-07-31 12:53:35 -0700798 unsigned second_actual = 0;
Neeti Desai465491e2012-07-31 12:53:35 -0700799
800#if DEVICE_TREE
801 struct dt_table *table;
Joel Kingaa335dc2013-06-03 16:11:08 -0700802 struct dt_entry dt_entry;
Neeti Desai465491e2012-07-31 12:53:35 -0700803 unsigned dt_table_offset;
Deepa Dinamani7aaf83d2012-12-21 11:27:01 -0800804 uint32_t dt_actual;
Deepa Dinamani19648b42013-09-05 17:05:55 -0700805 uint32_t dt_hdr_size;
Neeti Desai465491e2012-07-31 12:53:35 -0700806#endif
Maunik Shah78a85e52014-03-02 17:47:58 +0530807 if (check_format_bit())
808 boot_into_recovery = 1;
809
Deepa Dinamani41fa8d62013-05-23 13:25:36 -0700810 if (!boot_into_recovery) {
811 memset(ffbm_mode_string, '\0', sizeof(ffbm_mode_string));
812 rcode = get_ffbm(ffbm_mode_string, sizeof(ffbm_mode_string));
813 if (rcode <= 0) {
814 boot_into_ffbm = false;
815 if (rcode < 0)
816 dprintf(CRITICAL,"failed to get ffbm cookie");
817 } else
818 boot_into_ffbm = true;
819 } else
820 boot_into_ffbm = false;
Shashank Mittal23b8f422010-04-16 19:27:21 -0700821 uhdr = (struct boot_img_hdr *)EMMC_BOOT_IMG_HEADER_ADDR;
822 if (!memcmp(uhdr->magic, BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
823 dprintf(INFO, "Unified boot method!\n");
824 hdr = uhdr;
825 goto unified_boot;
826 }
Greg Griscod6250552011-06-29 14:40:23 -0700827 if (!boot_into_recovery) {
Kinson Chikf1a43512011-07-14 11:28:39 -0700828 index = partition_get_index("boot");
829 ptn = partition_get_offset(index);
830 if(ptn == 0) {
Shashank Mittal85b91f62010-10-30 10:12:38 -0700831 dprintf(CRITICAL, "ERROR: No boot partition found\n");
832 return -1;
833 }
Kinson Chikf1a43512011-07-14 11:28:39 -0700834 }
835 else {
836 index = partition_get_index("recovery");
837 ptn = partition_get_offset(index);
838 if(ptn == 0) {
Shashank Mittal85b91f62010-10-30 10:12:38 -0700839 dprintf(CRITICAL, "ERROR: No recovery partition found\n");
840 return -1;
841 }
Shashank Mittal23b8f422010-04-16 19:27:21 -0700842 }
843
Greg Griscod6250552011-06-29 14:40:23 -0700844 if (mmc_read(ptn + offset, (unsigned int *) buf, page_size)) {
Shashank Mittal23b8f422010-04-16 19:27:21 -0700845 dprintf(CRITICAL, "ERROR: Cannot read boot image header\n");
846 return -1;
847 }
Shashank Mittal23b8f422010-04-16 19:27:21 -0700848
849 if (memcmp(hdr->magic, BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
Kinson Chik kchik@codeaurora.org82e4ae62011-04-12 17:42:07 -0700850 dprintf(CRITICAL, "ERROR: Invalid boot image header\n");
Shashank Mittal23b8f422010-04-16 19:27:21 -0700851 return -1;
852 }
853
Subbaraman Narayanamurthyfbe13a02010-09-10 11:51:12 -0700854 if (hdr->page_size && (hdr->page_size != page_size)) {
855 page_size = hdr->page_size;
856 page_mask = page_size - 1;
Shashank Mittal23b8f422010-04-16 19:27:21 -0700857 }
858
Channagoud Kadabia22144f2013-03-20 11:49:01 -0700859 /*
860 * Update the kernel/ramdisk/tags address if the boot image header
861 * has default values, these default values come from mkbootimg when
862 * the boot image is flashed using fastboot flash:raw
863 */
864 update_ker_tags_rdisk_addr(hdr);
865
Deepa Dinamani0bf2f442012-10-19 11:41:06 -0700866 /* Get virtual addresses since the hdr saves physical addresses. */
867 hdr->kernel_addr = VA((addr_t)(hdr->kernel_addr));
868 hdr->ramdisk_addr = VA((addr_t)(hdr->ramdisk_addr));
869 hdr->tags_addr = VA((addr_t)(hdr->tags_addr));
Deepa Dinamani0e163a42013-05-24 17:08:15 -0700870
871 kernel_actual = ROUND_TO_PAGE(hdr->kernel_size, page_mask);
872 ramdisk_actual = ROUND_TO_PAGE(hdr->ramdisk_size, page_mask);
873
874 /* Check if the addresses in the header are valid. */
875 if (check_aboot_addr_range_overlap(hdr->kernel_addr, kernel_actual) ||
876 check_aboot_addr_range_overlap(hdr->ramdisk_addr, ramdisk_actual))
877 {
878 dprintf(CRITICAL, "kernel/ramdisk addresses overlap with aboot addresses.\n");
879 return -1;
880 }
881
882#ifndef DEVICE_TREE
883 if (check_aboot_addr_range_overlap(hdr->tags_addr, MAX_TAGS_SIZE))
884 {
885 dprintf(CRITICAL, "Tags addresses overlap with aboot addresses.\n");
886 return -1;
887 }
888#endif
889
Sridhar Parasuram78344412015-08-29 11:13:07 -0700890#if VERIFIED_BOOT
891 boot_verifier_init();
892#endif
893
894
Shashank Mittalcd98d472011-08-02 14:29:24 -0700895 /* Authenticate Kernel */
Amir Samuelov57a6fa22013-06-05 16:36:43 +0300896 dprintf(INFO, "use_signed_kernel=%d, is_unlocked=%d, is_tampered=%d.\n",
897 (int) target_use_signed_kernel(),
898 device.is_unlocked,
899 device.is_tampered);
900
Deepa Dinamani23b60d42013-06-24 18:10:52 -0700901 if(target_use_signed_kernel() && (!device.is_unlocked))
Subbaraman Narayanamurthy958fa242011-01-27 17:42:38 -0800902 {
Deepa Dinamani0e163a42013-05-24 17:08:15 -0700903 offset = 0;
904
Shashank Mittalcd98d472011-08-02 14:29:24 -0700905 image_addr = (unsigned char *)target_get_scratch_address();
Deepa Dinamani0e163a42013-05-24 17:08:15 -0700906
Deepa Dinamani7aaf83d2012-12-21 11:27:01 -0800907#if DEVICE_TREE
908 dt_actual = ROUND_TO_PAGE(hdr->dt_size, page_mask);
909 imagesize_actual = (page_size + kernel_actual + ramdisk_actual + dt_actual);
Deepa Dinamani0e163a42013-05-24 17:08:15 -0700910
Deepa Dinamanid14bb4d2013-07-12 17:28:29 -0700911 if (check_aboot_addr_range_overlap(hdr->tags_addr, dt_actual))
Deepa Dinamani0e163a42013-05-24 17:08:15 -0700912 {
913 dprintf(CRITICAL, "Device tree addresses overlap with aboot addresses.\n");
914 return -1;
915 }
Deepa Dinamani7aaf83d2012-12-21 11:27:01 -0800916#else
Channagoud Kadabi4b276512012-08-28 15:16:30 +0530917 imagesize_actual = (page_size + kernel_actual + ramdisk_actual);
Shashank Mittal162244e2011-08-08 19:01:25 -0700918
Deepa Dinamani0e163a42013-05-24 17:08:15 -0700919#endif
Shashank Mittal162244e2011-08-08 19:01:25 -0700920
Amol Jadib6be5c12012-11-14 13:39:51 -0800921 dprintf(INFO, "Loading boot image (%d): start\n", imagesize_actual);
Amol Jadi492d5a52013-03-15 16:12:34 -0700922 bs_set_timestamp(BS_KERNEL_LOAD_START);
Amol Jadib6be5c12012-11-14 13:39:51 -0800923
Deepa Dinamanid14bb4d2013-07-12 17:28:29 -0700924 if (check_aboot_addr_range_overlap(image_addr, imagesize_actual))
925 {
926 dprintf(CRITICAL, "Boot image buffer address overlaps with aboot addresses.\n");
927 return -1;
928 }
929
Shashank Mittalcd98d472011-08-02 14:29:24 -0700930 /* Read image without signature */
931 if (mmc_read(ptn + offset, (void *)image_addr, imagesize_actual))
932 {
933 dprintf(CRITICAL, "ERROR: Cannot read boot image\n");
934 return -1;
Subbaraman Narayanamurthy958fa242011-01-27 17:42:38 -0800935 }
Shashank Mittalcd98d472011-08-02 14:29:24 -0700936
Amol Jadib6be5c12012-11-14 13:39:51 -0800937 dprintf(INFO, "Loading boot image (%d): done\n", imagesize_actual);
Amol Jadi492d5a52013-03-15 16:12:34 -0700938 bs_set_timestamp(BS_KERNEL_LOAD_DONE);
Amol Jadib6be5c12012-11-14 13:39:51 -0800939
Shashank Mittalcd98d472011-08-02 14:29:24 -0700940 offset = imagesize_actual;
Deepa Dinamanid14bb4d2013-07-12 17:28:29 -0700941
942 if (check_aboot_addr_range_overlap(image_addr + offset, page_size))
943 {
944 dprintf(CRITICAL, "Signature read buffer address overlaps with aboot addresses.\n");
945 return -1;
946 }
947
Shashank Mittalcd98d472011-08-02 14:29:24 -0700948 /* Read signature */
949 if(mmc_read(ptn + offset, (void *)(image_addr + offset), page_size))
950 {
951 dprintf(CRITICAL, "ERROR: Cannot read boot image signature\n");
Deepa Dinamani0e163a42013-05-24 17:08:15 -0700952 return -1;
Shashank Mittalcd98d472011-08-02 14:29:24 -0700953 }
Amol Jadib6be5c12012-11-14 13:39:51 -0800954
Deepa Dinamani0e163a42013-05-24 17:08:15 -0700955 verify_signed_bootimg(image_addr, imagesize_actual);
Shashank Mittalcd98d472011-08-02 14:29:24 -0700956
Neeti Desai465491e2012-07-31 12:53:35 -0700957 /* Move kernel, ramdisk and device tree to correct address */
Shashank Mittalcd98d472011-08-02 14:29:24 -0700958 memmove((void*) hdr->kernel_addr, (char *)(image_addr + page_size), hdr->kernel_size);
959 memmove((void*) hdr->ramdisk_addr, (char *)(image_addr + page_size + kernel_actual), hdr->ramdisk_size);
Shashank Mittal162244e2011-08-08 19:01:25 -0700960
Neeti Desai465491e2012-07-31 12:53:35 -0700961 #if DEVICE_TREE
962 if(hdr->dt_size) {
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -0700963 dt_table_offset = ((uint32_t)image_addr + page_size + kernel_actual + ramdisk_actual + second_actual);
Deepa Dinamani19648b42013-09-05 17:05:55 -0700964 table = (struct dt_table*) dt_table_offset;
Neeti Desai465491e2012-07-31 12:53:35 -0700965
Deepa Dinamani19648b42013-09-05 17:05:55 -0700966 if (dev_tree_validate(table, hdr->page_size, &dt_hdr_size) != 0) {
Neeti Desai465491e2012-07-31 12:53:35 -0700967 dprintf(CRITICAL, "ERROR: Cannot validate Device Tree Table \n");
968 return -1;
969 }
Deepa Dinamani19648b42013-09-05 17:05:55 -0700970
Neeti Desai465491e2012-07-31 12:53:35 -0700971 /* Find index of device tree within device tree table */
Joel Kingaa335dc2013-06-03 16:11:08 -0700972 if(dev_tree_get_entry_info(table, &dt_entry) != 0){
Neeti Desai465491e2012-07-31 12:53:35 -0700973 dprintf(CRITICAL, "ERROR: Device Tree Blob cannot be found\n");
974 return -1;
975 }
976
Deepa Dinamani0e163a42013-05-24 17:08:15 -0700977 /* Validate and Read device device tree in the "tags_add */
Joel Kingaa335dc2013-06-03 16:11:08 -0700978 if (check_aboot_addr_range_overlap(hdr->tags_addr, dt_entry.size))
Deepa Dinamani0e163a42013-05-24 17:08:15 -0700979 {
980 dprintf(CRITICAL, "Device tree addresses overlap with aboot addresses.\n");
981 return -1;
982 }
983
Joel Kingaa335dc2013-06-03 16:11:08 -0700984 memmove((void *)hdr->tags_addr, (char *)dt_table_offset + dt_entry.offset, dt_entry.size);
Channagoud Kadabi35095622013-03-01 13:53:05 -0800985 } else {
Dima Zavin77e41f32013-03-06 16:10:43 -0800986 /*
987 * If appended dev tree is found, update the atags with
988 * memory address to the DTB appended location on RAM.
989 * Else update with the atags address in the kernel header
990 */
991 void *dtb;
992 dtb = dev_tree_appended((void*) hdr->kernel_addr,
Dima Zavine63e5572013-05-03 12:23:06 -0700993 hdr->kernel_size,
994 (void *)hdr->tags_addr);
Dima Zavin77e41f32013-03-06 16:10:43 -0800995 if (!dtb) {
996 dprintf(CRITICAL, "ERROR: Appended Device Tree Blob not found\n");
997 return -1;
998 }
Neeti Desai465491e2012-07-31 12:53:35 -0700999 }
1000 #endif
Shashank Mittal23b8f422010-04-16 19:27:21 -07001001 }
Shashank Mittalcd98d472011-08-02 14:29:24 -07001002 else
1003 {
Amol Jadib6be5c12012-11-14 13:39:51 -08001004 second_actual = ROUND_TO_PAGE(hdr->second_size, page_mask);
Shashank Mittalcd98d472011-08-02 14:29:24 -07001005
Amol Jadib6be5c12012-11-14 13:39:51 -08001006 dprintf(INFO, "Loading boot image (%d): start\n",
1007 kernel_actual + ramdisk_actual);
Amol Jadi492d5a52013-03-15 16:12:34 -07001008 bs_set_timestamp(BS_KERNEL_LOAD_START);
Amol Jadib6be5c12012-11-14 13:39:51 -08001009
1010 offset = page_size;
1011
1012 /* Load kernel */
1013 if (mmc_read(ptn + offset, (void *)hdr->kernel_addr, kernel_actual)) {
Shashank Mittalcd98d472011-08-02 14:29:24 -07001014 dprintf(CRITICAL, "ERROR: Cannot read kernel image\n");
1015 return -1;
1016 }
Amol Jadib6be5c12012-11-14 13:39:51 -08001017 offset += kernel_actual;
Shashank Mittalcd98d472011-08-02 14:29:24 -07001018
Amol Jadib6be5c12012-11-14 13:39:51 -08001019 /* Load ramdisk */
1020 if(ramdisk_actual != 0)
Shashank Mittalcd98d472011-08-02 14:29:24 -07001021 {
Amol Jadib6be5c12012-11-14 13:39:51 -08001022 if (mmc_read(ptn + offset, (void *)hdr->ramdisk_addr, ramdisk_actual)) {
Shashank Mittalcd98d472011-08-02 14:29:24 -07001023 dprintf(CRITICAL, "ERROR: Cannot read ramdisk image\n");
1024 return -1;
1025 }
1026 }
Amol Jadib6be5c12012-11-14 13:39:51 -08001027 offset += ramdisk_actual;
1028
1029 dprintf(INFO, "Loading boot image (%d): done\n",
1030 kernel_actual + ramdisk_actual);
Amol Jadi492d5a52013-03-15 16:12:34 -07001031 bs_set_timestamp(BS_KERNEL_LOAD_DONE);
Neeti Desai465491e2012-07-31 12:53:35 -07001032
1033 if(hdr->second_size != 0) {
Amol Jadib6be5c12012-11-14 13:39:51 -08001034 offset += second_actual;
1035 /* Second image loading not implemented. */
1036 ASSERT(0);
Neeti Desai465491e2012-07-31 12:53:35 -07001037 }
1038
1039 #if DEVICE_TREE
1040 if(hdr->dt_size != 0) {
Deepa Dinamani19648b42013-09-05 17:05:55 -07001041 /* Read the first page of device tree table into buffer */
Neeti Desai465491e2012-07-31 12:53:35 -07001042 if(mmc_read(ptn + offset,(unsigned int *) dt_buf, page_size)) {
1043 dprintf(CRITICAL, "ERROR: Cannot read the Device Tree Table\n");
1044 return -1;
1045 }
1046 table = (struct dt_table*) dt_buf;
1047
Deepa Dinamani19648b42013-09-05 17:05:55 -07001048 if (dev_tree_validate(table, hdr->page_size, &dt_hdr_size) != 0) {
Neeti Desai465491e2012-07-31 12:53:35 -07001049 dprintf(CRITICAL, "ERROR: Cannot validate Device Tree Table \n");
1050 return -1;
1051 }
1052
Deepa Dinamani19648b42013-09-05 17:05:55 -07001053 table = (struct dt_table*) memalign(CACHE_LINE, dt_hdr_size);
1054 if (!table)
1055 return -1;
1056
1057 /* Read the entire device tree table into buffer */
1058 if(mmc_read(ptn + offset,(unsigned int *) table, dt_hdr_size)) {
1059 dprintf(CRITICAL, "ERROR: Cannot read the Device Tree Table\n");
1060 return -1;
1061 }
1062
Joel Kingaa335dc2013-06-03 16:11:08 -07001063 /* Find index of device tree within device tree table */
1064 if(dev_tree_get_entry_info(table, &dt_entry) != 0){
Neeti Desai465491e2012-07-31 12:53:35 -07001065 dprintf(CRITICAL, "ERROR: Getting device tree address failed\n");
1066 return -1;
1067 }
1068
Deepa Dinamani0e163a42013-05-24 17:08:15 -07001069 /* Validate and Read device device tree in the "tags_add */
Joel Kingaa335dc2013-06-03 16:11:08 -07001070 if (check_aboot_addr_range_overlap(hdr->tags_addr, dt_entry.size))
Deepa Dinamani0e163a42013-05-24 17:08:15 -07001071 {
1072 dprintf(CRITICAL, "Device tree addresses overlap with aboot addresses.\n");
1073 return -1;
1074 }
1075
Joel Kingaa335dc2013-06-03 16:11:08 -07001076 if(mmc_read(ptn + offset + dt_entry.offset,
1077 (void *)hdr->tags_addr, dt_entry.size)) {
Neeti Desai465491e2012-07-31 12:53:35 -07001078 dprintf(CRITICAL, "ERROR: Cannot read device tree\n");
1079 return -1;
1080 }
Amir Samuelov57a6fa22013-06-05 16:36:43 +03001081 #ifdef TZ_SAVE_KERNEL_HASH
1082 aboot_save_boot_hash_mmc(hdr->kernel_addr, kernel_actual,
1083 hdr->ramdisk_addr, ramdisk_actual,
1084 ptn, offset, hdr->dt_size);
1085 #endif /* TZ_SAVE_KERNEL_HASH */
1086
Channagoud Kadabi35095622013-03-01 13:53:05 -08001087 } else {
Aparna Mallavarapuf5432e42014-06-03 22:15:54 +05301088
1089 /* Validate the tags_addr */
1090 if (check_aboot_addr_range_overlap(hdr->tags_addr, kernel_actual))
1091 {
1092 dprintf(CRITICAL, "Device tree addresses overlap with aboot addresses.\n");
1093 return -1;
1094 }
Dima Zavin77e41f32013-03-06 16:10:43 -08001095 /*
1096 * If appended dev tree is found, update the atags with
1097 * memory address to the DTB appended location on RAM.
1098 * Else update with the atags address in the kernel header
1099 */
1100 void *dtb;
1101 dtb = dev_tree_appended((void*) hdr->kernel_addr,
Dima Zavine63e5572013-05-03 12:23:06 -07001102 kernel_actual,
1103 (void *)hdr->tags_addr);
Dima Zavin77e41f32013-03-06 16:10:43 -08001104 if (!dtb) {
1105 dprintf(CRITICAL, "ERROR: Appended Device Tree Blob not found\n");
1106 return -1;
1107 }
Neeti Desai465491e2012-07-31 12:53:35 -07001108 }
1109 #endif
Shashank Mittalcd98d472011-08-02 14:29:24 -07001110 }
Sridhar Parasuram78344412015-08-29 11:13:07 -07001111#if VERIFIED_BOOT
1112 if(boot_verify_get_state() == ORANGE)
1113 {
1114 dprintf(CRITICAL,
1115 "Your device has been unlocked and can't be trusted.\nWait for 5 seconds before proceeding\n");
1116 mdelay(5000);
1117 }
1118
1119 // send root of trust
1120 if(!send_rot_command((uint32_t)device.is_unlocked))
1121 ASSERT(0);
1122#endif
1123
Shashank Mittal23b8f422010-04-16 19:27:21 -07001124
Stanimir Varbanov69ec5462013-07-18 18:17:42 +03001125 if (boot_into_recovery && !device.is_unlocked && !device.is_tampered)
1126 target_load_ssd_keystore();
1127
Shashank Mittal23b8f422010-04-16 19:27:21 -07001128unified_boot:
Shashank Mittal23b8f422010-04-16 19:27:21 -07001129
Dima Zavin77e41f32013-03-06 16:10:43 -08001130 boot_linux((void *)hdr->kernel_addr, (void *)hdr->tags_addr,
Dima Zavinbd3daa02013-03-26 11:06:44 -07001131 (const char *)hdr->cmdline, board_machtype(),
Shashank Mittal23b8f422010-04-16 19:27:21 -07001132 (void *)hdr->ramdisk_addr, hdr->ramdisk_size);
1133
1134 return 0;
1135}
1136
Dima Zavin214cc642009-01-26 11:16:21 -08001137int boot_linux_from_flash(void)
1138{
1139 struct boot_img_hdr *hdr = (void*) buf;
Dima Zavin214cc642009-01-26 11:16:21 -08001140 struct ptentry *ptn;
1141 struct ptable *ptable;
1142 unsigned offset = 0;
Chandan Uddarajude85d3f2010-01-05 16:32:33 -08001143
Shashank Mittalcd98d472011-08-02 14:29:24 -07001144 unsigned char *image_addr = 0;
1145 unsigned kernel_actual;
1146 unsigned ramdisk_actual;
1147 unsigned imagesize_actual;
Amol Jadib6be5c12012-11-14 13:39:51 -08001148 unsigned second_actual;
Shashank Mittalcd98d472011-08-02 14:29:24 -07001149
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -07001150#if DEVICE_TREE
1151 struct dt_table *table;
Joel Kingaa335dc2013-06-03 16:11:08 -07001152 struct dt_entry dt_entry;
Deepa Dinamani7aaf83d2012-12-21 11:27:01 -08001153 uint32_t dt_actual;
Deepa Dinamani19648b42013-09-05 17:05:55 -07001154 uint32_t dt_hdr_size;
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -07001155#endif
1156
David Ng183a7422009-12-07 14:55:21 -08001157 if (target_is_emmc_boot()) {
1158 hdr = (struct boot_img_hdr *)EMMC_BOOT_IMG_HEADER_ADDR;
1159 if (memcmp(hdr->magic, BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
1160 dprintf(CRITICAL, "ERROR: Invalid boot image header\n");
1161 return -1;
1162 }
1163 goto continue_boot;
1164 }
1165
Dima Zavin214cc642009-01-26 11:16:21 -08001166 ptable = flash_get_ptable();
1167 if (ptable == NULL) {
1168 dprintf(CRITICAL, "ERROR: Partition table not found\n");
1169 return -1;
1170 }
1171
Chandan Uddarajude85d3f2010-01-05 16:32:33 -08001172 if(!boot_into_recovery)
1173 {
1174 ptn = ptable_find(ptable, "boot");
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -07001175
Chandan Uddarajude85d3f2010-01-05 16:32:33 -08001176 if (ptn == NULL) {
1177 dprintf(CRITICAL, "ERROR: No boot partition found\n");
1178 return -1;
1179 }
1180 }
1181 else
1182 {
1183 ptn = ptable_find(ptable, "recovery");
1184 if (ptn == NULL) {
1185 dprintf(CRITICAL, "ERROR: No recovery partition found\n");
1186 return -1;
1187 }
Dima Zavin214cc642009-01-26 11:16:21 -08001188 }
1189
Shashank Mittaldcc2e352009-11-19 19:11:16 -08001190 if (flash_read(ptn, offset, buf, page_size)) {
Dima Zavin214cc642009-01-26 11:16:21 -08001191 dprintf(CRITICAL, "ERROR: Cannot read boot image header\n");
1192 return -1;
1193 }
Dima Zavin214cc642009-01-26 11:16:21 -08001194
1195 if (memcmp(hdr->magic, BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
Kinson Chik kchik@codeaurora.org82e4ae62011-04-12 17:42:07 -07001196 dprintf(CRITICAL, "ERROR: Invalid boot image header\n");
Dima Zavin214cc642009-01-26 11:16:21 -08001197 return -1;
1198 }
1199
Shashank Mittaldcc2e352009-11-19 19:11:16 -08001200 if (hdr->page_size != page_size) {
Kinson Chik kchik@codeaurora.org82e4ae62011-04-12 17:42:07 -07001201 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 -08001202 return -1;
1203 }
1204
Channagoud Kadabia22144f2013-03-20 11:49:01 -07001205 /*
1206 * Update the kernel/ramdisk/tags address if the boot image header
1207 * has default values, these default values come from mkbootimg when
1208 * the boot image is flashed using fastboot flash:raw
1209 */
1210 update_ker_tags_rdisk_addr(hdr);
1211
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001212 /* Get virtual addresses since the hdr saves physical addresses. */
Deepa Dinamani0e163a42013-05-24 17:08:15 -07001213 hdr->kernel_addr = VA((addr_t)(hdr->kernel_addr));
1214 hdr->ramdisk_addr = VA((addr_t)(hdr->ramdisk_addr));
1215 hdr->tags_addr = VA((addr_t)(hdr->tags_addr));
1216
1217 kernel_actual = ROUND_TO_PAGE(hdr->kernel_size, page_mask);
1218 ramdisk_actual = ROUND_TO_PAGE(hdr->ramdisk_size, page_mask);
1219
1220 /* Check if the addresses in the header are valid. */
1221 if (check_aboot_addr_range_overlap(hdr->kernel_addr, kernel_actual) ||
1222 check_aboot_addr_range_overlap(hdr->ramdisk_addr, ramdisk_actual))
1223 {
1224 dprintf(CRITICAL, "kernel/ramdisk addresses overlap with aboot addresses.\n");
1225 return -1;
1226 }
1227
1228#ifndef DEVICE_TREE
1229 if (check_aboot_addr_range_overlap(hdr->tags_addr, MAX_TAGS_SIZE))
1230 {
1231 dprintf(CRITICAL, "Tags addresses overlap with aboot addresses.\n");
1232 return -1;
1233 }
1234#endif
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001235
Shashank Mittalcd98d472011-08-02 14:29:24 -07001236 /* Authenticate Kernel */
Deepa Dinamani23b60d42013-06-24 18:10:52 -07001237 if(target_use_signed_kernel() && (!device.is_unlocked))
Shashank Mittalcd98d472011-08-02 14:29:24 -07001238 {
1239 image_addr = (unsigned char *)target_get_scratch_address();
Deepa Dinamani0e163a42013-05-24 17:08:15 -07001240 offset = 0;
1241
Deepa Dinamani7aaf83d2012-12-21 11:27:01 -08001242#if DEVICE_TREE
1243 dt_actual = ROUND_TO_PAGE(hdr->dt_size, page_mask);
1244 imagesize_actual = (page_size + kernel_actual + ramdisk_actual + dt_actual);
Deepa Dinamani0e163a42013-05-24 17:08:15 -07001245
1246 if (check_aboot_addr_range_overlap(hdr->tags_addr, hdr->dt_size))
1247 {
1248 dprintf(CRITICAL, "Device tree addresses overlap with aboot addresses.\n");
1249 return -1;
1250 }
Deepa Dinamani7aaf83d2012-12-21 11:27:01 -08001251#else
Shashank Mittalcd98d472011-08-02 14:29:24 -07001252 imagesize_actual = (page_size + kernel_actual + ramdisk_actual);
Deepa Dinamani7aaf83d2012-12-21 11:27:01 -08001253#endif
Shashank Mittal162244e2011-08-08 19:01:25 -07001254
Amol Jadib6be5c12012-11-14 13:39:51 -08001255 dprintf(INFO, "Loading boot image (%d): start\n", imagesize_actual);
Amol Jadi492d5a52013-03-15 16:12:34 -07001256 bs_set_timestamp(BS_KERNEL_LOAD_START);
Amol Jadib6be5c12012-11-14 13:39:51 -08001257
Shashank Mittalcd98d472011-08-02 14:29:24 -07001258 /* Read image without signature */
1259 if (flash_read(ptn, offset, (void *)image_addr, imagesize_actual))
1260 {
1261 dprintf(CRITICAL, "ERROR: Cannot read boot image\n");
1262 return -1;
1263 }
Dima Zavin214cc642009-01-26 11:16:21 -08001264
Amol Jadib6be5c12012-11-14 13:39:51 -08001265 dprintf(INFO, "Loading boot image (%d): done\n", imagesize_actual);
Amol Jadi492d5a52013-03-15 16:12:34 -07001266 bs_set_timestamp(BS_KERNEL_LOAD_DONE);
Amol Jadib6be5c12012-11-14 13:39:51 -08001267
Shashank Mittalcd98d472011-08-02 14:29:24 -07001268 offset = imagesize_actual;
1269 /* Read signature */
1270 if (flash_read(ptn, offset, (void *)(image_addr + offset), page_size))
1271 {
1272 dprintf(CRITICAL, "ERROR: Cannot read boot image signature\n");
Deepa Dinamani0e163a42013-05-24 17:08:15 -07001273 return -1;
Shashank Mittalcd98d472011-08-02 14:29:24 -07001274 }
Shashank Mittalcd98d472011-08-02 14:29:24 -07001275
Deepa Dinamani0e163a42013-05-24 17:08:15 -07001276 verify_signed_bootimg(image_addr, imagesize_actual);
Shashank Mittalcd98d472011-08-02 14:29:24 -07001277
1278 /* Move kernel and ramdisk to correct address */
1279 memmove((void*) hdr->kernel_addr, (char *)(image_addr + page_size), hdr->kernel_size);
1280 memmove((void*) hdr->ramdisk_addr, (char *)(image_addr + page_size + kernel_actual), hdr->ramdisk_size);
Deepa Dinamani7aaf83d2012-12-21 11:27:01 -08001281#if DEVICE_TREE
Deepa Dinamani0e163a42013-05-24 17:08:15 -07001282 /* Validate and Read device device tree in the "tags_add */
Joel Kingaa335dc2013-06-03 16:11:08 -07001283 if (check_aboot_addr_range_overlap(hdr->tags_addr, dt_entry.size))
Deepa Dinamani0e163a42013-05-24 17:08:15 -07001284 {
1285 dprintf(CRITICAL, "Device tree addresses overlap with aboot addresses.\n");
1286 return -1;
1287 }
1288
Deepa Dinamani7aaf83d2012-12-21 11:27:01 -08001289 memmove((void*) hdr->tags_addr, (char *)(image_addr + page_size + kernel_actual + ramdisk_actual), hdr->dt_size);
1290#endif
Shashank Mittal162244e2011-08-08 19:01:25 -07001291
1292 /* Make sure everything from scratch address is read before next step!*/
Shashank Mittala0032282011-08-26 14:50:11 -07001293 if(device.is_tampered)
Shashank Mittal162244e2011-08-08 19:01:25 -07001294 {
1295 write_device_info_flash(&device);
1296 }
Channagoud Kadabi5c86fe32012-02-16 10:58:48 +05301297#if USE_PCOM_SECBOOT
1298 set_tamper_flag(device.is_tampered);
1299#endif
Shashank Mittalcd98d472011-08-02 14:29:24 -07001300 }
1301 else
1302 {
Shashank Mittal162244e2011-08-08 19:01:25 -07001303 offset = page_size;
1304
Amol Jadib6be5c12012-11-14 13:39:51 -08001305 kernel_actual = ROUND_TO_PAGE(hdr->kernel_size, page_mask);
1306 ramdisk_actual = ROUND_TO_PAGE(hdr->ramdisk_size, page_mask);
1307 second_actual = ROUND_TO_PAGE(hdr->second_size, page_mask);
1308
1309 dprintf(INFO, "Loading boot image (%d): start\n",
1310 kernel_actual + ramdisk_actual);
Amol Jadi492d5a52013-03-15 16:12:34 -07001311 bs_set_timestamp(BS_KERNEL_LOAD_START);
Amol Jadib6be5c12012-11-14 13:39:51 -08001312
1313 if (flash_read(ptn, offset, (void *)hdr->kernel_addr, kernel_actual)) {
Shashank Mittalcd98d472011-08-02 14:29:24 -07001314 dprintf(CRITICAL, "ERROR: Cannot read kernel image\n");
1315 return -1;
1316 }
Amol Jadib6be5c12012-11-14 13:39:51 -08001317 offset += kernel_actual;
Shashank Mittalcd98d472011-08-02 14:29:24 -07001318
Amol Jadib6be5c12012-11-14 13:39:51 -08001319 if (flash_read(ptn, offset, (void *)hdr->ramdisk_addr, ramdisk_actual)) {
Shashank Mittalcd98d472011-08-02 14:29:24 -07001320 dprintf(CRITICAL, "ERROR: Cannot read ramdisk image\n");
1321 return -1;
1322 }
Amol Jadib6be5c12012-11-14 13:39:51 -08001323 offset += ramdisk_actual;
1324
1325 dprintf(INFO, "Loading boot image (%d): done\n",
1326 kernel_actual + ramdisk_actual);
Amol Jadi492d5a52013-03-15 16:12:34 -07001327 bs_set_timestamp(BS_KERNEL_LOAD_DONE);
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -07001328
1329 if(hdr->second_size != 0) {
Amol Jadib6be5c12012-11-14 13:39:51 -08001330 offset += second_actual;
1331 /* Second image loading not implemented. */
1332 ASSERT(0);
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -07001333 }
1334
1335#if DEVICE_TREE
1336 if(hdr->dt_size != 0) {
1337
1338 /* Read the device tree table into buffer */
1339 if(flash_read(ptn, offset, (void *) dt_buf, page_size)) {
1340 dprintf(CRITICAL, "ERROR: Cannot read the Device Tree Table\n");
1341 return -1;
1342 }
1343
1344 table = (struct dt_table*) dt_buf;
1345
Deepa Dinamani19648b42013-09-05 17:05:55 -07001346 if (dev_tree_validate(table, hdr->page_size, &dt_hdr_size) != 0) {
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -07001347 dprintf(CRITICAL, "ERROR: Cannot validate Device Tree Table \n");
1348 return -1;
1349 }
1350
Deepa Dinamani19648b42013-09-05 17:05:55 -07001351 table = (struct dt_table*) memalign(CACHE_LINE, dt_hdr_size);
1352 if (!table)
1353 return -1;
1354
1355 /* Read the entire device tree table into buffer */
1356 if(flash_read(ptn, offset, (void *)table, dt_hdr_size)) {
1357 dprintf(CRITICAL, "ERROR: Cannot read the Device Tree Table\n");
1358 return -1;
1359 }
1360
1361
Joel Kingaa335dc2013-06-03 16:11:08 -07001362 /* Find index of device tree within device tree table */
1363 if(dev_tree_get_entry_info(table, &dt_entry) != 0){
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -07001364 dprintf(CRITICAL, "ERROR: Getting device tree address failed\n");
1365 return -1;
1366 }
1367
Deepa Dinamani0e163a42013-05-24 17:08:15 -07001368 /* Validate and Read device device tree in the "tags_add */
Joel Kingaa335dc2013-06-03 16:11:08 -07001369 if (check_aboot_addr_range_overlap(hdr->tags_addr, dt_entry.size))
Deepa Dinamani0e163a42013-05-24 17:08:15 -07001370 {
1371 dprintf(CRITICAL, "Device tree addresses overlap with aboot addresses.\n");
1372 return -1;
1373 }
1374
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -07001375 /* Read device device tree in the "tags_add */
Joel Kingaa335dc2013-06-03 16:11:08 -07001376 if(flash_read(ptn, offset + dt_entry.offset,
1377 (void *)hdr->tags_addr, dt_entry.size)) {
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -07001378 dprintf(CRITICAL, "ERROR: Cannot read device tree\n");
1379 return -1;
1380 }
1381 }
1382#endif
1383
Shashank Mittalcd98d472011-08-02 14:29:24 -07001384 }
David Ng183a7422009-12-07 14:55:21 -08001385continue_boot:
Dima Zavin214cc642009-01-26 11:16:21 -08001386
Dima Zavin214cc642009-01-26 11:16:21 -08001387 /* TODO: create/pass atags to kernel */
1388
Ajay Dudanie28a6072011-07-01 13:59:46 -07001389 boot_linux((void *)hdr->kernel_addr, (void *)hdr->tags_addr,
Dima Zavinbd3daa02013-03-26 11:06:44 -07001390 (const char *)hdr->cmdline, board_machtype(),
Dima Zavin214cc642009-01-26 11:16:21 -08001391 (void *)hdr->ramdisk_addr, hdr->ramdisk_size);
1392
1393 return 0;
1394}
Brian Swetland9c4c0752009-01-25 16:23:50 -08001395
Channagoud Kadabi132ff552013-04-19 14:34:44 -07001396BUF_DMA_ALIGN(info_buf, 4096);
Shashank Mittal162244e2011-08-08 19:01:25 -07001397void write_device_info_mmc(device_info *dev)
1398{
1399 struct device_info *info = (void*) info_buf;
1400 unsigned long long ptn = 0;
1401 unsigned long long size;
1402 int index = INVALID_PTN;
1403
1404 index = partition_get_index("aboot");
1405 ptn = partition_get_offset(index);
1406 if(ptn == 0)
1407 {
1408 return;
1409 }
1410
1411 size = partition_get_size(index);
1412
1413 memcpy(info, dev, sizeof(device_info));
1414
1415 if(mmc_write((ptn + size - 512), 512, (void *)info_buf))
1416 {
1417 dprintf(CRITICAL, "ERROR: Cannot write device info\n");
1418 return;
1419 }
1420}
1421
1422void read_device_info_mmc(device_info *dev)
1423{
1424 struct device_info *info = (void*) info_buf;
1425 unsigned long long ptn = 0;
1426 unsigned long long size;
1427 int index = INVALID_PTN;
1428
1429 index = partition_get_index("aboot");
1430 ptn = partition_get_offset(index);
1431 if(ptn == 0)
1432 {
1433 return;
1434 }
1435
1436 size = partition_get_size(index);
1437
1438 if(mmc_read((ptn + size - 512), (void *)info_buf, 512))
1439 {
1440 dprintf(CRITICAL, "ERROR: Cannot read device info\n");
1441 return;
1442 }
1443
1444 if (memcmp(info->magic, DEVICE_MAGIC, DEVICE_MAGIC_SIZE))
1445 {
1446 memcpy(info->magic, DEVICE_MAGIC, DEVICE_MAGIC_SIZE);
1447 info->is_unlocked = 0;
Shashank Mittala0032282011-08-26 14:50:11 -07001448 info->is_tampered = 0;
Ameya Thakur11cf1a62013-08-05 12:44:48 -07001449 info->charger_screen_enabled = 0;
Sridhar Parasuram78344412015-08-29 11:13:07 -07001450#if VERIFIED_BOOT
1451 info->verity_mode = 1;
1452#endif
Shashank Mittal162244e2011-08-08 19:01:25 -07001453 write_device_info_mmc(info);
1454 }
1455 memcpy(dev, info, sizeof(device_info));
1456}
1457
1458void write_device_info_flash(device_info *dev)
1459{
1460 struct device_info *info = (void *) info_buf;
1461 struct ptentry *ptn;
1462 struct ptable *ptable;
1463
1464 ptable = flash_get_ptable();
1465 if (ptable == NULL)
1466 {
1467 dprintf(CRITICAL, "ERROR: Partition table not found\n");
1468 return;
1469 }
1470
1471 ptn = ptable_find(ptable, "devinfo");
1472 if (ptn == NULL)
1473 {
1474 dprintf(CRITICAL, "ERROR: No boot partition found\n");
1475 return;
1476 }
1477
1478 memcpy(info, dev, sizeof(device_info));
1479
1480 if (flash_write(ptn, 0, (void *)info_buf, page_size))
1481 {
1482 dprintf(CRITICAL, "ERROR: Cannot write device info\n");
1483 return;
1484 }
1485}
1486
1487void read_device_info_flash(device_info *dev)
1488{
1489 struct device_info *info = (void*) info_buf;
1490 struct ptentry *ptn;
1491 struct ptable *ptable;
1492
1493 ptable = flash_get_ptable();
1494 if (ptable == NULL)
1495 {
1496 dprintf(CRITICAL, "ERROR: Partition table not found\n");
1497 return;
1498 }
1499
1500 ptn = ptable_find(ptable, "devinfo");
1501 if (ptn == NULL)
1502 {
1503 dprintf(CRITICAL, "ERROR: No boot partition found\n");
1504 return;
1505 }
1506
1507 if (flash_read(ptn, 0, (void *)info_buf, page_size))
1508 {
1509 dprintf(CRITICAL, "ERROR: Cannot write device info\n");
1510 return;
1511 }
1512
1513 if (memcmp(info->magic, DEVICE_MAGIC, DEVICE_MAGIC_SIZE))
1514 {
Shashank Mittal162244e2011-08-08 19:01:25 -07001515 memcpy(info->magic, DEVICE_MAGIC, DEVICE_MAGIC_SIZE);
1516 info->is_unlocked = 0;
Shashank Mittala0032282011-08-26 14:50:11 -07001517 info->is_tampered = 0;
Shashank Mittal162244e2011-08-08 19:01:25 -07001518 write_device_info_flash(info);
1519 }
1520 memcpy(dev, info, sizeof(device_info));
1521}
1522
1523void write_device_info(device_info *dev)
1524{
1525 if(target_is_emmc_boot())
1526 {
1527 write_device_info_mmc(dev);
1528 }
1529 else
1530 {
1531 write_device_info_flash(dev);
1532 }
1533}
1534
1535void read_device_info(device_info *dev)
1536{
1537 if(target_is_emmc_boot())
1538 {
1539 read_device_info_mmc(dev);
1540 }
1541 else
1542 {
1543 read_device_info_flash(dev);
1544 }
1545}
1546
1547void reset_device_info()
1548{
1549 dprintf(ALWAYS, "reset_device_info called.");
Shashank Mittala0032282011-08-26 14:50:11 -07001550 device.is_tampered = 0;
Shashank Mittal162244e2011-08-08 19:01:25 -07001551 write_device_info(&device);
1552}
1553
1554void set_device_root()
1555{
1556 dprintf(ALWAYS, "set_device_root called.");
Shashank Mittala0032282011-08-26 14:50:11 -07001557 device.is_tampered = 1;
Shashank Mittal162244e2011-08-08 19:01:25 -07001558 write_device_info(&device);
1559}
1560
Amol Jadicb524072012-08-09 16:40:18 -07001561#if DEVICE_TREE
1562int copy_dtb(uint8_t *boot_image_start)
1563{
1564 uint32 dt_image_offset = 0;
1565 uint32_t n;
1566 struct dt_table *table;
Joel Kingaa335dc2013-06-03 16:11:08 -07001567 struct dt_entry dt_entry;
Deepa Dinamani19648b42013-09-05 17:05:55 -07001568 uint32_t dt_hdr_size;
Amol Jadicb524072012-08-09 16:40:18 -07001569
1570 struct boot_img_hdr *hdr = (struct boot_img_hdr *) (boot_image_start);
1571
Amol Jadicb524072012-08-09 16:40:18 -07001572 if(hdr->dt_size != 0) {
1573
1574 /* add kernel offset */
1575 dt_image_offset += page_size;
1576 n = ROUND_TO_PAGE(hdr->kernel_size, page_mask);
1577 dt_image_offset += n;
1578
1579 /* add ramdisk offset */
1580 n = ROUND_TO_PAGE(hdr->ramdisk_size, page_mask);
1581 dt_image_offset += n;
1582
1583 /* add second offset */
1584 if(hdr->second_size != 0) {
1585 n = ROUND_TO_PAGE(hdr->second_size, page_mask);
1586 dt_image_offset += n;
1587 }
1588
1589 /* offset now point to start of dt.img */
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -07001590 table = (struct dt_table*)(boot_image_start + dt_image_offset);
Amol Jadicb524072012-08-09 16:40:18 -07001591
Deepa Dinamani19648b42013-09-05 17:05:55 -07001592 if (dev_tree_validate(table, hdr->page_size, &dt_hdr_size) != 0) {
Amol Jadicb524072012-08-09 16:40:18 -07001593 dprintf(CRITICAL, "ERROR: Cannot validate Device Tree Table \n");
1594 return -1;
1595 }
Joel Kingaa335dc2013-06-03 16:11:08 -07001596 /* Find index of device tree within device tree table */
1597 if(dev_tree_get_entry_info(table, &dt_entry) != 0){
Amol Jadicb524072012-08-09 16:40:18 -07001598 dprintf(CRITICAL, "ERROR: Getting device tree address failed\n");
1599 return -1;
1600 }
1601
Deepa Dinamani0e163a42013-05-24 17:08:15 -07001602 /* Validate and Read device device tree in the "tags_add */
Joel Kingaa335dc2013-06-03 16:11:08 -07001603 if (check_aboot_addr_range_overlap(hdr->tags_addr, dt_entry.size))
Deepa Dinamani0e163a42013-05-24 17:08:15 -07001604 {
1605 dprintf(CRITICAL, "Device tree addresses overlap with aboot addresses.\n");
1606 return -1;
1607 }
1608
Amol Jadicb524072012-08-09 16:40:18 -07001609 /* Read device device tree in the "tags_add */
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001610 memmove((void*) hdr->tags_addr,
Joel Kingaa335dc2013-06-03 16:11:08 -07001611 boot_image_start + dt_image_offset + dt_entry.offset,
1612 dt_entry.size);
Channagoud Kadabi8e9020f2013-04-16 11:24:32 -07001613 } else
1614 return -1;
Amol Jadicb524072012-08-09 16:40:18 -07001615
1616 /* Everything looks fine. Return success. */
1617 return 0;
1618}
1619#endif
1620
Brian Swetland9c4c0752009-01-25 16:23:50 -08001621void cmd_boot(const char *arg, void *data, unsigned sz)
1622{
1623 unsigned kernel_actual;
1624 unsigned ramdisk_actual;
Channagoud Kadabice737c82014-06-18 17:41:01 -07001625 uint32_t image_actual;
1626 uint32_t dt_actual = 0;
Channagoud Kadabi87c2dd62014-06-26 14:26:39 -07001627 uint32_t sig_actual = SIGNATURE_SIZE;
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001628 struct boot_img_hdr *hdr;
Brian Swetland9c4c0752009-01-25 16:23:50 -08001629 char *ptr = ((char*) data);
Channagoud Kadabi8e9020f2013-04-16 11:24:32 -07001630 int ret = 0;
1631 uint8_t dtb_copied = 0;
Brian Swetland9c4c0752009-01-25 16:23:50 -08001632
1633 if (sz < sizeof(hdr)) {
1634 fastboot_fail("invalid bootimage header");
1635 return;
1636 }
1637
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001638 hdr = (struct boot_img_hdr *)data;
Brian Swetland9c4c0752009-01-25 16:23:50 -08001639
1640 /* ensure commandline is terminated */
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001641 hdr->cmdline[BOOT_ARGS_SIZE-1] = 0;
Brian Swetland9c4c0752009-01-25 16:23:50 -08001642
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001643 if(target_is_emmc_boot() && hdr->page_size) {
1644 page_size = hdr->page_size;
Subbaraman Narayanamurthyfbe13a02010-09-10 11:51:12 -07001645 page_mask = page_size - 1;
1646 }
1647
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001648 kernel_actual = ROUND_TO_PAGE(hdr->kernel_size, page_mask);
1649 ramdisk_actual = ROUND_TO_PAGE(hdr->ramdisk_size, page_mask);
Channagoud Kadabice737c82014-06-18 17:41:01 -07001650#if DEVICE_TREE
1651 dt_actual = ROUND_TO_PAGE(hdr->dt_size, page_mask);
1652#endif
1653
1654 image_actual = ADD_OF(page_size, kernel_actual);
1655 image_actual = ADD_OF(image_actual, ramdisk_actual);
1656 image_actual = ADD_OF(image_actual, dt_actual);
1657
Channagoud Kadabi87c2dd62014-06-26 14:26:39 -07001658 if (target_use_signed_kernel() && (!device.is_unlocked))
1659 image_actual = ADD_OF(image_actual, sig_actual);
1660
Channagoud Kadabice737c82014-06-18 17:41:01 -07001661 /* sz should have atleast raw boot image */
1662 if (image_actual > sz) {
Channagoud Kadabi87c2dd62014-06-26 14:26:39 -07001663 fastboot_fail("bootimage: incomplete or not signed");
Channagoud Kadabice737c82014-06-18 17:41:01 -07001664 return;
1665 }
1666
1667 /* Verify the boot image
1668 * device & page_size are initialized in aboot_init
1669 */
1670 if (target_use_signed_kernel() && (!device.is_unlocked))
Channagoud Kadabi87c2dd62014-06-26 14:26:39 -07001671 /* Pass size excluding signature size, otherwise we would try to
1672 * access signature beyond its length
1673 */
1674 verify_signed_bootimg((uint32_t)data, (image_actual - sig_actual));
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001675
Channagoud Kadabia22144f2013-03-20 11:49:01 -07001676 /*
1677 * Update the kernel/ramdisk/tags address if the boot image header
1678 * has default values, these default values come from mkbootimg when
1679 * the boot image is flashed using fastboot flash:raw
1680 */
1681 update_ker_tags_rdisk_addr(hdr);
Dima Zavin3cadfff2013-03-21 14:30:48 -07001682
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001683 /* Get virtual addresses since the hdr saves physical addresses. */
1684 hdr->kernel_addr = VA(hdr->kernel_addr);
1685 hdr->ramdisk_addr = VA(hdr->ramdisk_addr);
1686 hdr->tags_addr = VA(hdr->tags_addr);
Brian Swetland9c4c0752009-01-25 16:23:50 -08001687
Deepa Dinamani0e163a42013-05-24 17:08:15 -07001688 /* Check if the addresses in the header are valid. */
1689 if (check_aboot_addr_range_overlap(hdr->kernel_addr, kernel_actual) ||
1690 check_aboot_addr_range_overlap(hdr->ramdisk_addr, ramdisk_actual))
1691 {
1692 dprintf(CRITICAL, "kernel/ramdisk addresses overlap with aboot addresses.\n");
Channagoud Kadabia54102a2013-12-03 11:19:20 -08001693 return;
Deepa Dinamani0e163a42013-05-24 17:08:15 -07001694 }
1695
Amol Jadicb524072012-08-09 16:40:18 -07001696#if DEVICE_TREE
1697 /* find correct dtb and copy it to right location */
Channagoud Kadabi8e9020f2013-04-16 11:24:32 -07001698 ret = copy_dtb(data);
1699
1700 dtb_copied = !ret ? 1 : 0;
Deepa Dinamani0e163a42013-05-24 17:08:15 -07001701#else
1702 if (check_aboot_addr_range_overlap(hdr->tags_addr, MAX_TAGS_SIZE))
1703 {
1704 dprintf(CRITICAL, "Tags addresses overlap with aboot addresses.\n");
Channagoud Kadabia54102a2013-12-03 11:19:20 -08001705 return;
Deepa Dinamani0e163a42013-05-24 17:08:15 -07001706 }
Channagoud Kadabi8e9020f2013-04-16 11:24:32 -07001707#endif
1708
1709 /* Load ramdisk & kernel */
1710 memmove((void*) hdr->ramdisk_addr, ptr + page_size + kernel_actual, hdr->ramdisk_size);
1711 memmove((void*) hdr->kernel_addr, ptr + page_size, hdr->kernel_size);
1712
1713#if DEVICE_TREE
1714 /*
1715 * If dtb is not found look for appended DTB in the kernel.
1716 * If appended dev tree is found, update the atags with
1717 * memory address to the DTB appended location on RAM.
1718 * Else update with the atags address in the kernel header
1719 */
1720 if (!dtb_copied) {
1721 void *dtb;
Dima Zavine63e5572013-05-03 12:23:06 -07001722 dtb = dev_tree_appended((void *)hdr->kernel_addr, hdr->kernel_size,
1723 (void *)hdr->tags_addr);
Channagoud Kadabi8e9020f2013-04-16 11:24:32 -07001724 if (!dtb) {
1725 fastboot_fail("dtb not found");
1726 return;
1727 }
Amol Jadicb524072012-08-09 16:40:18 -07001728 }
1729#endif
Brian Swetland9c4c0752009-01-25 16:23:50 -08001730
Deepa Dinamani0e163a42013-05-24 17:08:15 -07001731#ifndef DEVICE_TREE
1732 if (check_aboot_addr_range_overlap(hdr->tags_addr, MAX_TAGS_SIZE))
1733 {
1734 dprintf(CRITICAL, "Tags addresses overlap with aboot addresses.\n");
Channagoud Kadabia54102a2013-12-03 11:19:20 -08001735 return;
Deepa Dinamani0e163a42013-05-24 17:08:15 -07001736 }
1737#endif
1738
Brian Swetland9c4c0752009-01-25 16:23:50 -08001739 fastboot_okay("");
1740 udc_stop();
1741
Dima Zavin77e41f32013-03-06 16:10:43 -08001742 boot_linux((void*) hdr->kernel_addr, (void*) hdr->tags_addr,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001743 (const char*) hdr->cmdline, board_machtype(),
1744 (void*) hdr->ramdisk_addr, hdr->ramdisk_size);
Brian Swetland9c4c0752009-01-25 16:23:50 -08001745}
1746
Sridhar Parasuram901bb702014-10-24 14:06:03 -07001747void cmd_erase_nand(const char *arg, void *data, unsigned sz)
Dima Zavin214cc642009-01-26 11:16:21 -08001748{
1749 struct ptentry *ptn;
1750 struct ptable *ptable;
1751
1752 ptable = flash_get_ptable();
1753 if (ptable == NULL) {
1754 fastboot_fail("partition table doesn't exist");
1755 return;
1756 }
1757
1758 ptn = ptable_find(ptable, arg);
1759 if (ptn == NULL) {
1760 fastboot_fail("unknown partition name");
1761 return;
1762 }
1763
1764 if (flash_erase(ptn)) {
1765 fastboot_fail("failed to erase partition");
1766 return;
1767 }
1768 fastboot_okay("");
1769}
1770
Bikas Gurungd48bd242010-09-04 19:54:32 -07001771
1772void cmd_erase_mmc(const char *arg, void *data, unsigned sz)
1773{
Kun Liang2f1601a2013-08-12 16:29:54 +08001774 BUF_DMA_ALIGN(out, DEFAULT_ERASE_SIZE);
Bikas Gurungd48bd242010-09-04 19:54:32 -07001775 unsigned long long ptn = 0;
Oliver Wang0e0dfa72013-10-22 18:40:13 +08001776 unsigned long long size = 0;
Kinson Chikf1a43512011-07-14 11:28:39 -07001777 int index = INVALID_PTN;
Bikas Gurungd48bd242010-09-04 19:54:32 -07001778
Kinson Chikf1a43512011-07-14 11:28:39 -07001779 index = partition_get_index(arg);
1780 ptn = partition_get_offset(index);
Oliver Wang0e0dfa72013-10-22 18:40:13 +08001781 size = partition_get_size(index);
Neeti Desaica8c9602011-10-06 11:40:00 -07001782
Kinson Chikf1a43512011-07-14 11:28:39 -07001783 if(ptn == 0) {
Neeti Desaica8c9602011-10-06 11:40:00 -07001784 fastboot_fail("Partition table doesn't exist\n");
Bikas Gurungd48bd242010-09-04 19:54:32 -07001785 return;
1786 }
Kun Liang2f1601a2013-08-12 16:29:54 +08001787
Oliver Wang0e0dfa72013-10-22 18:40:13 +08001788#if MMC_SDHCI_SUPPORT
1789 if (mmc_erase_card(ptn, size)) {
1790 fastboot_fail("failed to erase partition\n");
1791 return;
1792 }
1793#else
Kun Liang2f1601a2013-08-12 16:29:54 +08001794 size = partition_get_size(index);
1795 if (size > DEFAULT_ERASE_SIZE)
1796 size = DEFAULT_ERASE_SIZE;
1797
neetidb4b24d62012-01-20 12:13:09 -08001798 /* Simple inefficient version of erase. Just writing
Kun Liang2f1601a2013-08-12 16:29:54 +08001799 0 in first several blocks */
1800 if (mmc_write(ptn , size, (unsigned int *)out)) {
neetidb4b24d62012-01-20 12:13:09 -08001801 fastboot_fail("failed to erase partition");
Bikas Gurungd48bd242010-09-04 19:54:32 -07001802 return;
1803 }
Oliver Wang0e0dfa72013-10-22 18:40:13 +08001804#endif
Sridhar Parasuram78344412015-08-29 11:13:07 -07001805#if VERIFIED_BOOT
1806 if(!(strncmp(arg, "userdata", 8)))
1807 if(send_delete_keys_to_tz())
1808 ASSERT(0);
1809#endif
Bikas Gurungd48bd242010-09-04 19:54:32 -07001810 fastboot_okay("");
1811}
1812
Sridhar Parasuram901bb702014-10-24 14:06:03 -07001813void cmd_erase(const char *arg, void *data, unsigned sz)
1814{
Sridhar Parasuram78344412015-08-29 11:13:07 -07001815
1816#if VERIFIED_BOOT
1817 if(!device.is_unlocked)
1818 {
1819 fastboot_fail("device is locked. Cannot erase");
1820 return;
1821 }
1822#endif
1823
Sridhar Parasuram901bb702014-10-24 14:06:03 -07001824 if(target_is_emmc_boot())
1825 cmd_erase_mmc(arg, data, sz);
1826 else
1827 cmd_erase_nand(arg, data, sz);
1828}
Bikas Gurungd48bd242010-09-04 19:54:32 -07001829
Ajay Dudani5c761132011-04-07 20:19:04 -07001830void cmd_flash_mmc_img(const char *arg, void *data, unsigned sz)
Shashank Mittal23b8f422010-04-16 19:27:21 -07001831{
1832 unsigned long long ptn = 0;
Subbaraman Narayanamurthyc95b5b12010-08-31 13:19:48 -07001833 unsigned long long size = 0;
Kinson Chikf1a43512011-07-14 11:28:39 -07001834 int index = INVALID_PTN;
Subbaraman Narayanamurthyc95b5b12010-08-31 13:19:48 -07001835
Greg Grisco6e754772011-06-23 12:19:39 -07001836 if (!strcmp(arg, "partition"))
1837 {
1838 dprintf(INFO, "Attempt to write partition image.\n");
Neeti Desai5f26aff2011-09-30 10:27:40 -07001839 if (write_partition(sz, (unsigned char *) data)) {
Greg Grisco6e754772011-06-23 12:19:39 -07001840 fastboot_fail("failed to write partition");
Shashank Mittal23b8f422010-04-16 19:27:21 -07001841 return;
1842 }
1843 }
Greg Grisco6e754772011-06-23 12:19:39 -07001844 else
1845 {
Kinson Chikf1a43512011-07-14 11:28:39 -07001846 index = partition_get_index(arg);
1847 ptn = partition_get_offset(index);
Greg Grisco6e754772011-06-23 12:19:39 -07001848 if(ptn == 0) {
1849 fastboot_fail("partition table doesn't exist");
1850 return;
1851 }
Shashank Mittal23b8f422010-04-16 19:27:21 -07001852
Greg Grisco6e754772011-06-23 12:19:39 -07001853 if (!strcmp(arg, "boot") || !strcmp(arg, "recovery")) {
1854 if (memcmp((void *)data, BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
1855 fastboot_fail("image is not a boot image");
1856 return;
1857 }
1858 }
Subbaraman Narayanamurthyc95b5b12010-08-31 13:19:48 -07001859
Kinson Chikf1a43512011-07-14 11:28:39 -07001860 size = partition_get_size(index);
Greg Grisco6e754772011-06-23 12:19:39 -07001861 if (ROUND_TO_PAGE(sz,511) > size) {
1862 fastboot_fail("size too large");
1863 return;
1864 }
1865 else if (mmc_write(ptn , sz, (unsigned int *)data)) {
1866 fastboot_fail("flash write failure");
1867 return;
1868 }
Shashank Mittal23b8f422010-04-16 19:27:21 -07001869 }
1870 fastboot_okay("");
1871 return;
1872}
1873
Ajay Dudani5c761132011-04-07 20:19:04 -07001874void cmd_flash_mmc_sparse_img(const char *arg, void *data, unsigned sz)
1875{
1876 unsigned int chunk;
1877 unsigned int chunk_data_sz;
1878 sparse_header_t *sparse_header;
1879 chunk_header_t *chunk_header;
Ajay Dudaniab18f022011-05-12 14:39:22 -07001880 uint32_t total_blocks = 0;
Ajay Dudani5c761132011-04-07 20:19:04 -07001881 unsigned long long ptn = 0;
Channagoud Kadabi65b91002011-10-11 17:34:33 +05301882 unsigned long long size = 0;
Kinson Chikf1a43512011-07-14 11:28:39 -07001883 int index = INVALID_PTN;
vijay kumard6ebd9a2015-04-24 20:26:19 +05301884 /*End of the sparse image address*/
1885 uint32_t data_end = (uint32_t)data + sz;
Ajay Dudani5c761132011-04-07 20:19:04 -07001886
Kinson Chikf1a43512011-07-14 11:28:39 -07001887 index = partition_get_index(arg);
1888 ptn = partition_get_offset(index);
1889 if(ptn == 0) {
Ajay Dudani5c761132011-04-07 20:19:04 -07001890 fastboot_fail("partition table doesn't exist");
1891 return;
1892 }
1893
Channagoud Kadabi65b91002011-10-11 17:34:33 +05301894 size = partition_get_size(index);
vijay kumard6ebd9a2015-04-24 20:26:19 +05301895
1896 if (sz < sizeof(sparse_header_t)) {
1897 fastboot_fail("size too low");
Channagoud Kadabi65b91002011-10-11 17:34:33 +05301898 return;
1899 }
1900
Ajay Dudani5c761132011-04-07 20:19:04 -07001901 /* Read and skip over sparse image header */
1902 sparse_header = (sparse_header_t *) data;
vijay kumard6ebd9a2015-04-24 20:26:19 +05301903
vijay kumar05e00a52015-03-27 12:13:42 +05301904 if (((uint64_t)sparse_header->total_blks * (uint64_t)sparse_header->blk_sz) > size) {
Ajay Dudani876b3282012-12-21 14:12:17 -08001905 fastboot_fail("size too large");
1906 return;
1907 }
1908
vijay kumar3c9ccff2015-04-23 13:05:49 +05301909 data += sizeof(sparse_header_t);
vijay kumard6ebd9a2015-04-24 20:26:19 +05301910
1911 if (data_end < (uint32_t)data) {
1912 fastboot_fail("buffer overreads occured due to invalid sparse header");
1913 return;
1914 }
1915
vijay kumar3c9ccff2015-04-23 13:05:49 +05301916 if(sparse_header->file_hdr_sz != sizeof(sparse_header_t))
Ajay Dudani5c761132011-04-07 20:19:04 -07001917 {
vijay kumar3c9ccff2015-04-23 13:05:49 +05301918 fastboot_fail("sparse header size mismatch");
1919 return;
Ajay Dudani5c761132011-04-07 20:19:04 -07001920 }
1921
Ajay Dudanib06c05f2011-05-12 14:46:10 -07001922 dprintf (SPEW, "=== Sparse Image Header ===\n");
1923 dprintf (SPEW, "magic: 0x%x\n", sparse_header->magic);
1924 dprintf (SPEW, "major_version: 0x%x\n", sparse_header->major_version);
1925 dprintf (SPEW, "minor_version: 0x%x\n", sparse_header->minor_version);
1926 dprintf (SPEW, "file_hdr_sz: %d\n", sparse_header->file_hdr_sz);
1927 dprintf (SPEW, "chunk_hdr_sz: %d\n", sparse_header->chunk_hdr_sz);
1928 dprintf (SPEW, "blk_sz: %d\n", sparse_header->blk_sz);
1929 dprintf (SPEW, "total_blks: %d\n", sparse_header->total_blks);
1930 dprintf (SPEW, "total_chunks: %d\n", sparse_header->total_chunks);
Ajay Dudani5c761132011-04-07 20:19:04 -07001931
1932 /* Start processing chunks */
1933 for (chunk=0; chunk<sparse_header->total_chunks; chunk++)
1934 {
Aparna Mallavarapu4f829bb2015-03-28 01:41:08 +05301935 /* Make sure the total image size does not exceed the partition size */
1936 if(((uint64_t)total_blocks * (uint64_t)sparse_header->blk_sz) >= size) {
1937 fastboot_fail("size too large");
1938 return;
1939 }
Ajay Dudani5c761132011-04-07 20:19:04 -07001940 /* Read and skip over chunk header */
1941 chunk_header = (chunk_header_t *) data;
1942 data += sizeof(chunk_header_t);
1943
vijay kumard6ebd9a2015-04-24 20:26:19 +05301944 if (data_end < (uint32_t)data) {
1945 fastboot_fail("buffer overreads occured due to invalid sparse header");
1946 return;
1947 }
1948
Ajay Dudani5c761132011-04-07 20:19:04 -07001949 dprintf (SPEW, "=== Chunk Header ===\n");
1950 dprintf (SPEW, "chunk_type: 0x%x\n", chunk_header->chunk_type);
1951 dprintf (SPEW, "chunk_data_sz: 0x%x\n", chunk_header->chunk_sz);
1952 dprintf (SPEW, "total_size: 0x%x\n", chunk_header->total_sz);
1953
vijay kumard6ebd9a2015-04-24 20:26:19 +05301954 if(sparse_header->chunk_hdr_sz != sizeof(chunk_header_t))
Ajay Dudani5c761132011-04-07 20:19:04 -07001955 {
vijay kumard6ebd9a2015-04-24 20:26:19 +05301956 fastboot_fail("chunk header size mismatch");
1957 return;
Ajay Dudani5c761132011-04-07 20:19:04 -07001958 }
1959
1960 chunk_data_sz = sparse_header->blk_sz * chunk_header->chunk_sz;
Aparna Mallavarapu4f829bb2015-03-28 01:41:08 +05301961
1962 /* Make sure multiplication does not overflow uint32 size */
1963 if (sparse_header->blk_sz && (chunk_header->chunk_sz != chunk_data_sz / sparse_header->blk_sz))
1964 {
1965 fastboot_fail("Bogus size sparse and chunk header");
1966 return;
1967 }
1968
1969 /* Make sure that the chunk size calculated from sparse image does not
1970 * exceed partition size
1971 */
1972 if ((uint64_t)total_blocks * (uint64_t)sparse_header->blk_sz + chunk_data_sz > size)
1973 {
1974 fastboot_fail("Chunk data size exceeds partition size");
1975 return;
1976 }
1977
Ajay Dudani5c761132011-04-07 20:19:04 -07001978 switch (chunk_header->chunk_type)
1979 {
1980 case CHUNK_TYPE_RAW:
1981 if(chunk_header->total_sz != (sparse_header->chunk_hdr_sz +
1982 chunk_data_sz))
1983 {
1984 fastboot_fail("Bogus chunk size for chunk type Raw");
1985 return;
1986 }
1987
vijay kumard6ebd9a2015-04-24 20:26:19 +05301988 if (data_end < (uint32_t)data + chunk_data_sz) {
1989 fastboot_fail("buffer overreads occured due to invalid sparse header");
1990 return;
1991 }
1992
Ajay Dudaniab18f022011-05-12 14:39:22 -07001993 if(mmc_write(ptn + ((uint64_t)total_blocks*sparse_header->blk_sz),
1994 chunk_data_sz,
1995 (unsigned int*)data))
Ajay Dudani5c761132011-04-07 20:19:04 -07001996 {
1997 fastboot_fail("flash write failure");
1998 return;
1999 }
Aparna Mallavarapu4f829bb2015-03-28 01:41:08 +05302000 if(total_blocks > (UINT_MAX - chunk_header->chunk_sz)) {
2001 fastboot_fail("Bogus size for RAW chunk type");
2002 return;
2003 }
Ajay Dudani5c761132011-04-07 20:19:04 -07002004 total_blocks += chunk_header->chunk_sz;
2005 data += chunk_data_sz;
2006 break;
2007
2008 case CHUNK_TYPE_DONT_CARE:
Aparna Mallavarapu4f829bb2015-03-28 01:41:08 +05302009 if(total_blocks > (UINT_MAX - chunk_header->chunk_sz)) {
2010 fastboot_fail("bogus size for chunk DONT CARE type");
2011 return;
2012 }
Kinson Chik kchik@codeaurora.orgda29b1e2011-05-06 17:36:39 -07002013 total_blocks += chunk_header->chunk_sz;
2014 break;
2015
Ajay Dudani5c761132011-04-07 20:19:04 -07002016 case CHUNK_TYPE_CRC:
2017 if(chunk_header->total_sz != sparse_header->chunk_hdr_sz)
2018 {
2019 fastboot_fail("Bogus chunk size for chunk type Dont Care");
2020 return;
2021 }
Aparna Mallavarapu4f829bb2015-03-28 01:41:08 +05302022 if(total_blocks > (UINT_MAX - chunk_header->chunk_sz)) {
2023 fastboot_fail("bogus size for chunk CRC type");
2024 return;
2025 }
Ajay Dudani5c761132011-04-07 20:19:04 -07002026 total_blocks += chunk_header->chunk_sz;
vijay kumard6ebd9a2015-04-24 20:26:19 +05302027 if ((uint32_t)data > UINT_MAX - chunk_data_sz) {
2028 fastboot_fail("integer overflow occured");
2029 return;
2030 }
Ajay Dudani5c761132011-04-07 20:19:04 -07002031 data += chunk_data_sz;
vijay kumard6ebd9a2015-04-24 20:26:19 +05302032 if (data_end < (uint32_t)data) {
2033 fastboot_fail("buffer overreads occured due to invalid sparse header");
2034 return;
2035 }
Ajay Dudani5c761132011-04-07 20:19:04 -07002036 break;
2037
Kinson Chik kchik@codeaurora.orgda29b1e2011-05-06 17:36:39 -07002038 default:
Ajay Dudani5c761132011-04-07 20:19:04 -07002039 fastboot_fail("Unknown chunk type");
2040 return;
2041 }
2042 }
2043
Ajay Dudani0c6927b2011-05-18 11:12:16 -07002044 dprintf(INFO, "Wrote %d blocks, expected to write %d blocks\n",
2045 total_blocks, sparse_header->total_blks);
2046
2047 if(total_blocks != sparse_header->total_blks)
2048 {
2049 fastboot_fail("sparse image write failure");
2050 }
Ajay Dudani5c761132011-04-07 20:19:04 -07002051
2052 fastboot_okay("");
2053 return;
2054}
2055
2056void cmd_flash_mmc(const char *arg, void *data, unsigned sz)
2057{
2058 sparse_header_t *sparse_header;
kchik@codeaurora.orgbce18ea2011-04-18 20:22:28 -07002059 /* 8 Byte Magic + 2048 Byte xml + Encrypted Data */
2060 unsigned int *magic_number = (unsigned int *) data;
Ajay Dudani5c761132011-04-07 20:19:04 -07002061
kchik@codeaurora.orgbce18ea2011-04-18 20:22:28 -07002062#ifdef SSD_ENABLE
sundarajan srinivasand4b1c482013-02-27 14:15:43 -08002063 int ret=0;
2064 uint32 major_version=0;
2065 uint32 minor_version=0;
2066
2067 ret = scm_svc_version(&major_version,&minor_version);
2068 if(!ret)
2069 {
2070 if(major_version >= 2)
2071 {
Amir Samuelovbb65ce02013-05-05 12:20:18 +03002072 if( !strcmp(arg, "ssd") || !strcmp(arg, "tqs") )
sundarajan srinivasand4b1c482013-02-27 14:15:43 -08002073 {
2074 ret = encrypt_scm((uint32 **) &data, &sz);
2075 if (ret != 0) {
2076 dprintf(CRITICAL, "ERROR: Encryption Failure\n");
2077 return;
2078 }
2079
Amir Samuelovbb65ce02013-05-05 12:20:18 +03002080 /* Protect only for SSD */
2081 if (!strcmp(arg, "ssd")) {
2082 ret = scm_protect_keystore((uint32 *) data, sz);
2083 if (ret != 0) {
2084 dprintf(CRITICAL, "ERROR: scm_protect_keystore Failed\n");
2085 return;
2086 }
sundarajan srinivasand4b1c482013-02-27 14:15:43 -08002087 }
2088 }
2089 else
2090 {
2091 ret = decrypt_scm_v2((uint32 **) &data, &sz);
2092 if(ret != 0)
2093 {
2094 dprintf(CRITICAL,"ERROR: Decryption Failure\n");
2095 return;
2096 }
2097 }
2098 }
2099 else
2100 {
2101 if (magic_number[0] == DECRYPT_MAGIC_0 &&
2102 magic_number[1] == DECRYPT_MAGIC_1)
2103 {
2104 ret = decrypt_scm((uint32 **) &data, &sz);
2105 if (ret != 0) {
2106 dprintf(CRITICAL, "ERROR: Invalid secure image\n");
2107 return;
2108 }
2109 }
2110 else if (magic_number[0] == ENCRYPT_MAGIC_0 &&
2111 magic_number[1] == ENCRYPT_MAGIC_1)
2112 {
2113 ret = encrypt_scm((uint32 **) &data, &sz);
2114 if (ret != 0) {
2115 dprintf(CRITICAL, "ERROR: Encryption Failure\n");
2116 return;
2117 }
2118 }
kchik@codeaurora.orgbce18ea2011-04-18 20:22:28 -07002119 }
2120 }
sundarajan srinivasand4b1c482013-02-27 14:15:43 -08002121 else
Neeti Desai127b9e02012-03-20 16:11:23 -07002122 {
sundarajan srinivasand4b1c482013-02-27 14:15:43 -08002123 dprintf(CRITICAL,"INVALID SVC Version\n");
2124 return;
Neeti Desai127b9e02012-03-20 16:11:23 -07002125 }
sundarajan srinivasand4b1c482013-02-27 14:15:43 -08002126#endif /* SSD_ENABLE */
Neeti Desai127b9e02012-03-20 16:11:23 -07002127
Sridhar Parasuram78344412015-08-29 11:13:07 -07002128#if VERIFIED_BOOT
2129 if(!device.is_unlocked)
2130 {
2131 fastboot_fail("device is locked. Cannot flash images");
2132 return;
2133 }
2134#endif
2135
kchik@codeaurora.orgbce18ea2011-04-18 20:22:28 -07002136 sparse_header = (sparse_header_t *) data;
Ajay Dudani5c761132011-04-07 20:19:04 -07002137 if (sparse_header->magic != SPARSE_HEADER_MAGIC)
2138 cmd_flash_mmc_img(arg, data, sz);
2139 else
2140 cmd_flash_mmc_sparse_img(arg, data, sz);
Sridhar Parasuram78344412015-08-29 11:13:07 -07002141
2142#if VERIFIED_BOOT
2143 if((!strncmp(arg, "system", 6)) && !device.verity_mode)
2144 {
2145 // reset dm_verity mode to enforcing
2146 device.verity_mode = 1;
2147 write_device_info(&device);
2148 }
2149#endif
2150
Ajay Dudani5c761132011-04-07 20:19:04 -07002151 return;
2152}
2153
Sridhar Parasuram901bb702014-10-24 14:06:03 -07002154void cmd_flash_nand(const char *arg, void *data, unsigned sz)
Dima Zavin214cc642009-01-26 11:16:21 -08002155{
2156 struct ptentry *ptn;
2157 struct ptable *ptable;
2158 unsigned extra = 0;
2159
2160 ptable = flash_get_ptable();
2161 if (ptable == NULL) {
2162 fastboot_fail("partition table doesn't exist");
2163 return;
2164 }
2165
2166 ptn = ptable_find(ptable, arg);
2167 if (ptn == NULL) {
2168 fastboot_fail("unknown partition name");
2169 return;
2170 }
2171
2172 if (!strcmp(ptn->name, "boot") || !strcmp(ptn->name, "recovery")) {
2173 if (memcmp((void *)data, BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
2174 fastboot_fail("image is not a boot image");
2175 return;
2176 }
2177 }
2178
Amol Jadi5c61a952012-05-04 17:05:35 -07002179 if (!strcmp(ptn->name, "system")
Deepa Dinamani13e32c42012-03-12 14:34:17 -07002180 || !strcmp(ptn->name, "userdata")
2181 || !strcmp(ptn->name, "persist")
2182 || !strcmp(ptn->name, "recoveryfs")) {
Channagoud Kadabi404a7062011-03-21 19:27:50 +05302183 if (flash_ecc_bch_enabled())
2184 /* Spare data bytes for 8 bit ECC increased by 4 */
2185 extra = ((page_size >> 9) * 20);
2186 else
2187 extra = ((page_size >> 9) * 16);
2188 } else
Shashank Mittaldcc2e352009-11-19 19:11:16 -08002189 sz = ROUND_TO_PAGE(sz, page_mask);
Dima Zavin214cc642009-01-26 11:16:21 -08002190
2191 dprintf(INFO, "writing %d bytes to '%s'\n", sz, ptn->name);
2192 if (flash_write(ptn, extra, data, sz)) {
2193 fastboot_fail("flash write failure");
2194 return;
2195 }
2196 dprintf(INFO, "partition '%s' updated\n", ptn->name);
2197 fastboot_okay("");
2198}
2199
Sridhar Parasuram901bb702014-10-24 14:06:03 -07002200void cmd_flash(const char *arg, void *data, unsigned sz)
2201{
2202 if(target_is_emmc_boot())
2203 cmd_flash_mmc(arg, data, sz);
2204 else
2205 cmd_flash_nand(arg, data, sz);
2206}
2207
Dima Zavin214cc642009-01-26 11:16:21 -08002208void cmd_continue(const char *arg, void *data, unsigned sz)
2209{
2210 fastboot_okay("");
2211 udc_stop();
Shashank Mittald8c42bf2010-06-09 15:44:28 -07002212 if (target_is_emmc_boot())
2213 {
2214 boot_linux_from_mmc();
2215 }
2216 else
2217 {
2218 boot_linux_from_flash();
2219 }
Dima Zavin214cc642009-01-26 11:16:21 -08002220}
2221
Chandan Uddaraju94183c02010-01-15 15:13:59 -08002222void cmd_reboot(const char *arg, void *data, unsigned sz)
2223{
Shashank Mittald8c42bf2010-06-09 15:44:28 -07002224 dprintf(INFO, "rebooting the device\n");
Chandan Uddaraju94183c02010-01-15 15:13:59 -08002225 fastboot_okay("");
2226 reboot_device(0);
2227}
2228
2229void cmd_reboot_bootloader(const char *arg, void *data, unsigned sz)
2230{
Shashank Mittald8c42bf2010-06-09 15:44:28 -07002231 dprintf(INFO, "rebooting the device\n");
Chandan Uddaraju94183c02010-01-15 15:13:59 -08002232 fastboot_okay("");
2233 reboot_device(FASTBOOT_MODE);
2234}
2235
Ameya Thakur11cf1a62013-08-05 12:44:48 -07002236void cmd_oem_enable_charger_screen(const char *arg, void *data, unsigned size)
2237{
2238 dprintf(INFO, "Enabling charger screen check\n");
2239 device.charger_screen_enabled = 1;
2240 write_device_info(&device);
2241 fastboot_okay("");
2242}
2243
2244void cmd_oem_disable_charger_screen(const char *arg, void *data, unsigned size)
2245{
2246 dprintf(INFO, "Disabling charger screen check\n");
2247 device.charger_screen_enabled = 0;
2248 write_device_info(&device);
2249 fastboot_okay("");
2250}
2251
Unnati Gandhi15d08f92014-01-24 11:01:01 +05302252void cmd_oem_select_display_panel(const char *arg, void *data, unsigned size)
2253{
2254 dprintf(INFO, "Selecting display panel %s\n", arg);
2255 if (arg)
2256 strlcpy(device.display_panel, arg,
2257 sizeof(device.display_panel));
2258 write_device_info(&device);
2259 fastboot_okay("");
2260}
2261
Sridhar Parasuram78344412015-08-29 11:13:07 -07002262void cmd_oem_lock(const char *arg, void *data, unsigned sz)
2263{
2264 struct recovery_message msg;
2265 if(device.is_unlocked)
2266 {
2267 device.is_unlocked = 0;
2268 write_device_info(&device);
2269 // upon oem lock, reboot to recovery to wipe user data
2270 snprintf(msg.recovery, sizeof(msg.recovery), "recovery\n--wipe_data");
2271 write_misc(0, &msg, sizeof(msg));
2272 fastboot_okay("");
2273 reboot_device(RECOVERY_MODE);
2274 }
2275 fastboot_okay("");
2276}
2277
2278
Shashank Mittal162244e2011-08-08 19:01:25 -07002279void cmd_oem_unlock(const char *arg, void *data, unsigned sz)
2280{
2281 if(!device.is_unlocked)
2282 {
2283 device.is_unlocked = 1;
2284 write_device_info(&device);
Sridhar Parasuram78344412015-08-29 11:13:07 -07002285 struct recovery_message msg;
2286 snprintf(msg.recovery, sizeof(msg.recovery), "recovery\n--wipe_data");
2287 write_misc(0, &msg, sizeof(msg));
2288
2289 fastboot_okay("");
2290 reboot_device(RECOVERY_MODE);
Shashank Mittal162244e2011-08-08 19:01:25 -07002291 }
2292 fastboot_okay("");
2293}
2294
Shashank Mittala0032282011-08-26 14:50:11 -07002295void cmd_oem_devinfo(const char *arg, void *data, unsigned sz)
2296{
Unnati Gandhi15d08f92014-01-24 11:01:01 +05302297 char response[128];
Ameya Thakur11cf1a62013-08-05 12:44:48 -07002298 snprintf(response, sizeof(response), "\tDevice tampered: %s", (device.is_tampered ? "true" : "false"));
Shashank Mittala0032282011-08-26 14:50:11 -07002299 fastboot_info(response);
Ameya Thakur11cf1a62013-08-05 12:44:48 -07002300 snprintf(response, sizeof(response), "\tDevice unlocked: %s", (device.is_unlocked ? "true" : "false"));
2301 fastboot_info(response);
2302 snprintf(response, sizeof(response), "\tCharger screen enabled: %s", (device.charger_screen_enabled ? "true" : "false"));
Shashank Mittala0032282011-08-26 14:50:11 -07002303 fastboot_info(response);
Unnati Gandhi15d08f92014-01-24 11:01:01 +05302304 snprintf(response, sizeof(response), "\tDisplay panel: %s", (device.display_panel));
2305 fastboot_info(response);
Shashank Mittala0032282011-08-26 14:50:11 -07002306 fastboot_okay("");
2307}
2308
Channagoud Kadabi4c4884e2013-04-09 17:12:13 -07002309void cmd_preflash(const char *arg, void *data, unsigned sz)
2310{
2311 fastboot_okay("");
2312}
2313
Aparna Mallavarapuad8c1ec2013-08-23 17:55:47 +05302314static struct fbimage logo_header = {0};
2315struct fbimage* splash_screen_flash();
2316
2317int splash_screen_check_header(struct fbimage *logo)
2318{
2319 if (memcmp(logo->header.magic, LOGO_IMG_MAGIC, 8))
2320 return -1;
2321 if (logo->header.width == 0 || logo->header.height == 0)
2322 return -1;
2323 return 0;
2324}
2325
2326struct fbimage* splash_screen_flash()
Chandan Uddaraju2943fd62010-06-21 10:56:39 -07002327{
2328 struct ptentry *ptn;
2329 struct ptable *ptable;
2330 struct fbcon_config *fb_display = NULL;
Aparna Mallavarapuad8c1ec2013-08-23 17:55:47 +05302331 struct fbimage *logo = &logo_header;
Chandan Uddaraju2943fd62010-06-21 10:56:39 -07002332
Aparna Mallavarapuad8c1ec2013-08-23 17:55:47 +05302333
2334 ptable = flash_get_ptable();
2335 if (ptable == NULL) {
2336 dprintf(CRITICAL, "ERROR: Partition table not found\n");
2337 return NULL;
2338 }
2339 ptn = ptable_find(ptable, "splash");
2340 if (ptn == NULL) {
2341 dprintf(CRITICAL, "ERROR: splash Partition not found\n");
2342 return NULL;
2343 }
2344
2345 if (flash_read(ptn, 0,(unsigned int *) logo, sizeof(logo->header))) {
2346 dprintf(CRITICAL, "ERROR: Cannot read boot image header\n");
2347 return NULL;
2348 }
2349
2350 if (splash_screen_check_header(logo)) {
2351 dprintf(CRITICAL, "ERROR: Boot image header invalid\n");
2352 return NULL;
2353 }
2354
2355 fb_display = fbcon_display();
2356 if (fb_display) {
Vineet Bajajb42103d2014-09-09 12:29:46 +05302357 if ((logo->header.width != fb_display->width) || (logo->header.height != fb_display->height)) {
2358 dprintf(CRITICAL, "Logo config doesn't match with fb config. Fall back to default logo\n");
2359 return NULL;
Chandan Uddaraju2943fd62010-06-21 10:56:39 -07002360 }
Vineet Bajajb42103d2014-09-09 12:29:46 +05302361 uint8_t *base = (uint8_t *) fb_display->base;
Aparna Mallavarapuad8c1ec2013-08-23 17:55:47 +05302362 if (flash_read(ptn + sizeof(logo->header), 0,
2363 base,
2364 ((((logo->header.width * logo->header.height * fb_display->bpp/8) + 511) >> 9) << 9))) {
2365 fbcon_clear();
Vineet Bajajb42103d2014-09-09 12:29:46 +05302366 dprintf(CRITICAL, "ERROR: Cannot read splash image from partition\n");
Aparna Mallavarapuad8c1ec2013-08-23 17:55:47 +05302367 return NULL;
Chandan Uddaraju2943fd62010-06-21 10:56:39 -07002368 }
Aparna Mallavarapuad8c1ec2013-08-23 17:55:47 +05302369 logo->image = base;
2370 }
2371
2372 return logo;
2373}
2374
2375struct fbimage* splash_screen_mmc()
2376{
2377 int index = INVALID_PTN;
2378 unsigned long long ptn = 0;
2379 struct fbcon_config *fb_display = NULL;
2380 struct fbimage *logo = &logo_header;
2381
2382 index = partition_get_index("splash");
2383 if (index == 0) {
2384 dprintf(CRITICAL, "ERROR: splash Partition table not found\n");
2385 return NULL;
2386 }
2387
2388 ptn = partition_get_offset(index);
2389 if (ptn == 0) {
2390 dprintf(CRITICAL, "ERROR: splash Partition invalid\n");
2391 return NULL;
2392 }
2393
2394 if (mmc_read(ptn, (unsigned int *) logo, sizeof(logo->header))) {
2395 dprintf(CRITICAL, "ERROR: Cannot read splash image header\n");
2396 return NULL;
2397 }
2398
2399 if (splash_screen_check_header(logo)) {
2400 dprintf(CRITICAL, "ERROR: Splash image header invalid\n");
2401 return NULL;
2402 }
2403
2404 fb_display = fbcon_display();
2405 if (fb_display) {
Vineet Bajajb42103d2014-09-09 12:29:46 +05302406 if ((logo->header.width != fb_display->width) || (logo->header.height != fb_display->height)) {
2407 dprintf(CRITICAL, "Logo config doesn't match with fb config. Fall back default logo\n");
2408 return NULL;
2409 }
Aparna Mallavarapuad8c1ec2013-08-23 17:55:47 +05302410 uint8_t *base = (uint8_t *) fb_display->base;
Aparna Mallavarapuad8c1ec2013-08-23 17:55:47 +05302411 if (mmc_read(ptn + sizeof(logo->header),
2412 base,
2413 ((((logo->header.width * logo->header.height * fb_display->bpp/8) + 511) >> 9) << 9))) {
2414 fbcon_clear();
Vineet Bajajb42103d2014-09-09 12:29:46 +05302415 dprintf(CRITICAL, "ERROR: Cannot read splash image from partition\n");
Aparna Mallavarapuad8c1ec2013-08-23 17:55:47 +05302416 return NULL;
2417 }
2418
2419 logo->image = base;
2420 }
2421
2422 return logo;
2423}
2424
2425
2426struct fbimage* fetch_image_from_partition()
2427{
2428 if (target_is_emmc_boot()) {
2429 return splash_screen_mmc();
2430 } else {
2431 return splash_screen_flash();
Chandan Uddaraju2943fd62010-06-21 10:56:39 -07002432 }
2433}
2434
Channagoud Kadabi4c4884e2013-04-09 17:12:13 -07002435/* Get the size from partiton name */
2436static void get_partition_size(const char *arg, char *response)
2437{
2438 uint64_t ptn = 0;
2439 uint64_t size;
2440 int index = INVALID_PTN;
2441
2442 index = partition_get_index(arg);
2443
2444 if (index == INVALID_PTN)
2445 {
2446 dprintf(CRITICAL, "Invalid partition index\n");
2447 return;
2448 }
2449
2450 ptn = partition_get_offset(index);
2451
2452 if(!ptn)
2453 {
2454 dprintf(CRITICAL, "Invalid partition name %s\n", arg);
2455 return;
2456 }
2457
2458 size = partition_get_size(index);
2459
2460 snprintf(response, MAX_RSP_SIZE, "\t 0x%llx", size);
2461 return;
2462}
2463
2464/*
2465 * Publish the partition type & size info
2466 * fastboot getvar will publish the required information.
2467 * fastboot getvar partition_size:<partition_name>: partition size in hex
2468 * fastboot getvar partition_type:<partition_name>: partition type (ext/fat)
2469 */
2470static void publish_getvar_partition_info(struct getvar_partition_info *info, uint8_t num_parts)
2471{
2472 uint8_t i;
2473
2474 for (i = 0; i < num_parts; i++) {
2475 get_partition_size(info[i].part_name, info[i].size_response);
2476
2477 if (strlcat(info[i].getvar_size, info[i].part_name, MAX_GET_VAR_NAME_SIZE) >= MAX_GET_VAR_NAME_SIZE)
2478 {
2479 dprintf(CRITICAL, "partition size name truncated\n");
2480 return;
2481 }
2482 if (strlcat(info[i].getvar_type, info[i].part_name, MAX_GET_VAR_NAME_SIZE) >= MAX_GET_VAR_NAME_SIZE)
2483 {
2484 dprintf(CRITICAL, "partition type name truncated\n");
2485 return;
2486 }
2487
2488 /* publish partition size & type info */
2489 fastboot_publish((const char *) info[i].getvar_size, (const char *) info[i].size_response);
2490 fastboot_publish((const char *) info[i].getvar_type, (const char *) info[i].type_response);
2491 }
2492}
2493
Amol Jadi5edf3552013-07-23 14:15:34 -07002494/* register commands and variables for fastboot */
2495void aboot_fastboot_register_commands(void)
2496{
Sridhar Parasuram901bb702014-10-24 14:06:03 -07002497 int i;
Amol Jadi5edf3552013-07-23 14:15:34 -07002498
Sridhar Parasuram901bb702014-10-24 14:06:03 -07002499 struct fastboot_cmd_desc cmd_list[] = {
2500 /* By default the enabled list is empty. */
2501 {"", NULL},
2502 /* move commands enclosed within the below ifndef to here
2503 * if they need to be enabled in user build.
2504 */
2505#ifndef DISABLE_FASTBOOT_CMDS
2506 /* Register the following commands only for non-user builds */
2507 {"flash:", cmd_flash},
2508 {"erase:", cmd_erase},
2509 {"boot", cmd_boot},
2510 {"continue", cmd_continue},
2511 {"reboot", cmd_reboot},
2512 {"reboot-bootloader", cmd_reboot_bootloader},
2513 {"oem unlock", cmd_oem_unlock},
Sridhar Parasuram78344412015-08-29 11:13:07 -07002514 {"oem lock", cmd_oem_lock},
Sridhar Parasuram901bb702014-10-24 14:06:03 -07002515 {"oem device-info", cmd_oem_devinfo},
2516 {"preflash", cmd_preflash},
2517 {"oem enable-charger-screen", cmd_oem_enable_charger_screen},
2518 {"oem disable-charger-screen", cmd_oem_disable_charger_screen},
2519 {"oem select-display-panel", cmd_oem_select_display_panel},
2520#endif
2521 };
2522
2523 int fastboot_cmds_count = sizeof(cmd_list)/sizeof(cmd_list[0]);
2524 for (i = 1; i < fastboot_cmds_count; i++)
2525 fastboot_register(cmd_list[i].name,cmd_list[i].cb);
2526
Amol Jadi5edf3552013-07-23 14:15:34 -07002527 /* publish variables and their values */
2528 fastboot_publish("product", TARGET(BOARD));
2529 fastboot_publish("kernel", "lk");
2530 fastboot_publish("serialno", sn_buf);
2531
2532 /*
2533 * partition info is supported only for emmc partitions
2534 * Calling this for NAND prints some error messages which
2535 * is harmless but misleading. Avoid calling this for NAND
2536 * devices.
2537 */
2538 if (target_is_emmc_boot())
2539 publish_getvar_partition_info(part_info, ARRAY_SIZE(part_info));
2540
2541 /* Max download size supported */
Ameya Thakur11cf1a62013-08-05 12:44:48 -07002542 snprintf(max_download_size, MAX_RSP_SIZE, "\t0x%x",
2543 target_get_max_flash_size());
Amol Jadi5edf3552013-07-23 14:15:34 -07002544 fastboot_publish("max-download-size", (const char *) max_download_size);
Ameya Thakur11cf1a62013-08-05 12:44:48 -07002545 /* Is the charger screen check enabled */
2546 snprintf(charger_screen_enabled, MAX_RSP_SIZE, "%d",
2547 device.charger_screen_enabled);
2548 fastboot_publish("charger-screen-enabled",
2549 (const char *) charger_screen_enabled);
Unnati Gandhi15d08f92014-01-24 11:01:01 +05302550 snprintf(panel_display_mode, MAX_RSP_SIZE, "%s",
2551 device.display_panel);
2552 fastboot_publish("display-panel",
2553 (const char *) panel_display_mode);
Amol Jadi5edf3552013-07-23 14:15:34 -07002554}
2555
Brian Swetland9c4c0752009-01-25 16:23:50 -08002556void aboot_init(const struct app_descriptor *app)
2557{
Shashank Mittal4f99a882010-02-01 13:58:50 -08002558 unsigned reboot_mode = 0;
Pavel Nedev5d91d412013-04-29 11:34:24 +03002559 bool boot_into_fastboot = false;
Chandan Uddarajubedca152010-06-02 23:05:15 -07002560
Chandan Uddaraju2943fd62010-06-21 10:56:39 -07002561 /* Setup page size information for nand/emmc reads */
Shashank Mittald8c42bf2010-06-09 15:44:28 -07002562 if (target_is_emmc_boot())
2563 {
2564 page_size = 2048;
2565 page_mask = page_size - 1;
2566 }
2567 else
2568 {
2569 page_size = flash_page_size();
2570 page_mask = page_size - 1;
2571 }
2572
Deepa Dinamani0e163a42013-05-24 17:08:15 -07002573 ASSERT((MEMBASE + MEMSIZE) > MEMBASE);
2574
Ameya Thakur11cf1a62013-08-05 12:44:48 -07002575 read_device_info(&device);
Shashank Mittal162244e2011-08-08 19:01:25 -07002576
Aravind Venkateswarandb0d5262014-02-25 16:25:30 -08002577 /* Display splash screen if enabled */
2578#if DISPLAY_SPLASH_SCREEN
2579 dprintf(SPEW, "Display Init: Start\n");
Unnati Gandhi15d08f92014-01-24 11:01:01 +05302580 target_display_init(device.display_panel);
Aravind Venkateswarandb0d5262014-02-25 16:25:30 -08002581 dprintf(SPEW, "Display Init: Done\n");
2582#endif
2583
2584
Greg Griscod6250552011-06-29 14:40:23 -07002585 target_serialno((unsigned char *) sn_buf);
Ajay Dudanib06c05f2011-05-12 14:46:10 -07002586 dprintf(SPEW,"serial number: %s\n",sn_buf);
Subbaraman Narayanamurthyf17b4ae2011-02-16 20:19:56 -08002587
Dhaval Patel223ec952013-07-18 14:49:44 -07002588 memset(display_panel_buf, '\0', MAX_PANEL_BUF_SIZE);
2589
Chandan Uddaraju2943fd62010-06-21 10:56:39 -07002590 /* Check if we should do something other than booting up */
Ameya Thakur0b9c2442013-05-10 13:22:56 -07002591 if (keys_get_state(KEY_VOLUMEUP) && keys_get_state(KEY_VOLUMEDOWN))
Subbaraman Narayanamurthy0e445b02011-06-19 21:34:46 -07002592 {
Pavel Nedeva4c9d3a2013-05-15 14:42:34 +03002593 dprintf(ALWAYS,"dload mode key sequence detected\n");
2594 if (set_download_mode(EMERGENCY_DLOAD))
Ameya Thakur0b9c2442013-05-10 13:22:56 -07002595 {
Pavel Nedeva4c9d3a2013-05-15 14:42:34 +03002596 dprintf(CRITICAL,"dload mode not supported by target\n");
Ameya Thakur0b9c2442013-05-10 13:22:56 -07002597 }
2598 else
2599 {
2600 reboot_device(0);
Pavel Nedeva4c9d3a2013-05-15 14:42:34 +03002601 dprintf(CRITICAL,"Failed to reboot into dload mode\n");
Ameya Thakur0b9c2442013-05-10 13:22:56 -07002602 }
2603 boot_into_fastboot = true;
2604 }
2605 if (!boot_into_fastboot)
2606 {
2607 if (keys_get_state(KEY_HOME) || keys_get_state(KEY_VOLUMEUP))
2608 boot_into_recovery = 1;
2609 if (!boot_into_recovery &&
2610 (keys_get_state(KEY_BACK) || keys_get_state(KEY_VOLUMEDOWN)))
Pavel Nedev5d91d412013-04-29 11:34:24 +03002611 boot_into_fastboot = true;
Subbaraman Narayanamurthy0e445b02011-06-19 21:34:46 -07002612 }
Shashank Mittald8c42bf2010-06-09 15:44:28 -07002613 #if NO_KEYPAD_DRIVER
Kinson Chik0b1c8162011-08-31 16:31:57 -07002614 if (fastboot_trigger())
Pavel Nedev5d91d412013-04-29 11:34:24 +03002615 boot_into_fastboot = true;
Shashank Mittald8c42bf2010-06-09 15:44:28 -07002616 #endif
Chandan Uddarajubedca152010-06-02 23:05:15 -07002617
Ajay Dudani77421292010-10-27 19:34:06 -07002618 reboot_mode = check_reboot_mode();
2619 if (reboot_mode == RECOVERY_MODE) {
2620 boot_into_recovery = 1;
2621 } else if(reboot_mode == FASTBOOT_MODE) {
Pavel Nedev5d91d412013-04-29 11:34:24 +03002622 boot_into_fastboot = true;
Sridhar Parasuram78344412015-08-29 11:13:07 -07002623#if VERIFIED_BOOT
2624 } else if(reboot_mode == DM_VERITY_ENFORCING) {
2625 device.verity_mode = 1;
2626 write_device_info(&device);
2627 } else if(reboot_mode == DM_VERITY_LOGGING) {
2628 device.verity_mode = 0;
2629 write_device_info(&device);
2630 } else if(reboot_mode == DM_VERITY_KEYSCLEAR) {
2631 if(send_delete_keys_to_tz())
2632 ASSERT(0);
2633#endif
Ajay Dudani77421292010-10-27 19:34:06 -07002634 }
2635
Pavel Nedev5d91d412013-04-29 11:34:24 +03002636 if (!boot_into_fastboot)
Shashank Mittald8c42bf2010-06-09 15:44:28 -07002637 {
Pavel Nedev5d91d412013-04-29 11:34:24 +03002638 if (target_is_emmc_boot())
Shashank Mittala0032282011-08-26 14:50:11 -07002639 {
Pavel Nedev5d91d412013-04-29 11:34:24 +03002640 if(emmc_recovery_init())
2641 dprintf(ALWAYS,"error in emmc_recovery_init\n");
2642 if(target_use_signed_kernel())
Shashank Mittala0032282011-08-26 14:50:11 -07002643 {
Pavel Nedev5d91d412013-04-29 11:34:24 +03002644 if((device.is_unlocked) || (device.is_tampered))
2645 {
2646 #ifdef TZ_TAMPER_FUSE
2647 set_tamper_fuse_cmd();
2648 #endif
2649 #if USE_PCOM_SECBOOT
2650 set_tamper_flag(device.is_tampered);
2651 #endif
2652 }
Shashank Mittala0032282011-08-26 14:50:11 -07002653 }
Pavel Nedev5d91d412013-04-29 11:34:24 +03002654 boot_linux_from_mmc();
Shashank Mittala0032282011-08-26 14:50:11 -07002655 }
Pavel Nedev5d91d412013-04-29 11:34:24 +03002656 else
2657 {
2658 recovery_init();
2659 #if USE_PCOM_SECBOOT
2660 if((device.is_unlocked) || (device.is_tampered))
2661 set_tamper_flag(device.is_tampered);
2662 #endif
2663 boot_linux_from_flash();
2664 }
2665 dprintf(CRITICAL, "ERROR: Could not do normal boot. Reverting "
2666 "to fastboot mode.\n");
Shashank Mittald8c42bf2010-06-09 15:44:28 -07002667 }
Chandan Uddaraju2943fd62010-06-21 10:56:39 -07002668
Amol Jadi5edf3552013-07-23 14:15:34 -07002669 /* We are here means regular boot did not happen. Start fastboot. */
Channagoud Kadabi4c4884e2013-04-09 17:12:13 -07002670
Amol Jadi5edf3552013-07-23 14:15:34 -07002671 /* register aboot specific fastboot commands */
2672 aboot_fastboot_register_commands();
Amol Jadi57abe4c2011-05-24 15:47:27 -07002673
Amol Jadi5edf3552013-07-23 14:15:34 -07002674 /* dump partition table for debug info */
Kinson Chikf1a43512011-07-14 11:28:39 -07002675 partition_dump();
Amol Jadi5edf3552013-07-23 14:15:34 -07002676
2677 /* initialize and start fastboot */
2678 fastboot_init(target_get_scratch_address(), target_get_max_flash_size());
Brian Swetland9c4c0752009-01-25 16:23:50 -08002679}
2680
Deepa Dinamani41fa8d62013-05-23 13:25:36 -07002681uint32_t get_page_size()
2682{
2683 return page_size;
2684}
2685
Amir Samuelov57a6fa22013-06-05 16:36:43 +03002686/*
2687 * Calculated and save hash (SHA256) for non-signed boot image.
2688 *
2689 * Hash the same data that is checked on the signed boot image.
2690 * Kernel and Ramdisk are already read to memory buffers.
2691 * Need to read the entire device-tree from mmc
2692 * since non-signed image only read the DT tags of the relevant platform.
2693 *
2694 * @param kernel_addr - kernel bufer
2695 * @param kernel_actual - kernel size in bytes
2696 * @param ramdisk_addr - ramdisk buffer
2697 * @param ramdisk_actual - ramdisk size
2698 * @param ptn - partition
2699 * @param dt_offset - device tree offset on mmc partition
2700 * @param dt_size
2701 *
2702 * @return int - 0 on success, negative value on failure.
2703 */
2704int aboot_save_boot_hash_mmc(void *kernel_addr, unsigned kernel_actual,
2705 void *ramdisk_addr, unsigned ramdisk_actual,
2706 unsigned long long ptn,
2707 unsigned dt_offset, unsigned dt_size)
2708{
2709 SHA256_CTX sha256_ctx;
2710 char digest[32]={0};
2711 char *buf = (char *)target_get_scratch_address();
2712 unsigned dt_actual = ROUND_TO_PAGE(dt_size, page_mask);
2713 unsigned imagesize_actual = page_size + kernel_actual + ramdisk_actual + dt_actual;
2714
2715 SHA256_Init(&sha256_ctx);
2716
2717 /* Read Boot Header */
2718 if (mmc_read(ptn, buf, page_size))
2719 {
2720 dprintf(CRITICAL, "ERROR: mmc_read() fail.\n");
2721 return -1;
2722 }
2723 /* Read entire Device Tree */
2724 if (mmc_read(ptn + dt_offset, buf+page_size, dt_actual))
2725 {
2726 dprintf(CRITICAL, "ERROR: mmc_read() fail.\n");
2727 return -1;
2728 }
2729 SHA256_Update(&sha256_ctx, buf, page_size); // Boot Header
2730 SHA256_Update(&sha256_ctx, kernel_addr, kernel_actual);
2731 SHA256_Update(&sha256_ctx, ramdisk_addr, ramdisk_actual);
2732 SHA256_Update(&sha256_ctx, buf+page_size, dt_actual); // Device Tree
2733
2734 SHA256_Final(digest, &sha256_ctx);
2735
2736 save_kernel_hash_cmd(digest);
2737 dprintf(INFO, "aboot_save_boot_hash_mmc: imagesize_actual size %d bytes.\n", (int) imagesize_actual);
2738
2739 return 0;
2740}
2741
Brian Swetland9c4c0752009-01-25 16:23:50 -08002742APP_START(aboot)
2743 .init = aboot_init,
2744APP_END