blob: 3ae4f188e2a5f251ad30fbe63c8455b861407e5b [file] [log] [blame]
Brian Swetland9c4c0752009-01-25 16:23:50 -08001/*
2 * Copyright (c) 2009, Google Inc.
3 * All rights reserved.
4 *
Kuogee Hsieh55e92c52013-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 Kadabifc3b31f2014-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>
Sundarajan Srinivasan3827a102013-09-10 13:57:40 -070055#include <platform/iomap.h>
Sundarajan Srinivasane52065a2014-03-20 16:25:59 -070056#include <boot_device.h>
Shashank Mittald3e54dd2014-08-28 15:24:02 -070057#include <boot_verifier.h>
Dima Zavin214cc642009-01-26 11:16:21 -080058
Neeti Desai17379b82012-06-04 18:42:53 -070059#if DEVICE_TREE
60#include <libfdt.h>
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -070061#include <dev_tree.h>
Neeti Desai17379b82012-06-04 18:42:53 -070062#endif
63
Shashank Mittalcd98d472011-08-02 14:29:24 -070064#include "image_verify.h"
Shashank Mittal024c0332010-02-03 11:44:00 -080065#include "recovery.h"
Brian Swetland9c4c0752009-01-25 16:23:50 -080066#include "bootimg.h"
67#include "fastboot.h"
Ajay Dudani5c761132011-04-07 20:19:04 -070068#include "sparse_format.h"
Greg Grisco6e754772011-06-23 12:19:39 -070069#include "mmc.h"
Shashank Mittal162244e2011-08-08 19:01:25 -070070#include "devinfo.h"
Neeti Desai465491e2012-07-31 12:53:35 -070071#include "board.h"
Shashank Mittal162244e2011-08-08 19:01:25 -070072#include "scm.h"
kchik@codeaurora.orgbce18ea2011-04-18 20:22:28 -070073
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -070074extern bool target_use_signed_kernel(void);
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -070075extern void platform_uninit(void);
Channagoud Kadabi33defe22013-06-18 18:35:40 -070076extern void target_uninit(void);
Joonwoo Park61112782013-10-02 19:50:39 -070077extern int get_target_boot_params(const char *cmdline, const char *part,
78 char *buf, int buflen);
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -070079
80void write_device_info_mmc(device_info *dev);
81void write_device_info_flash(device_info *dev);
Channagoud Kadabi82cf5c62014-08-24 22:17:34 -070082static int aboot_save_boot_hash_mmc(uint32_t image_addr, uint32_t image_size);
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -070083
Sridhar Parasurame94e8152014-10-24 14:06:03 -070084/* fastboot command function pointer */
85typedef void (*fastboot_cmd_fn) (const char *, void *, unsigned);
86
87struct fastboot_cmd_desc {
88 char * name;
89 fastboot_cmd_fn cb;
90};
91
Subbaraman Narayanamurthyeb92bcc2010-07-20 14:32:46 -070092#define EXPAND(NAME) #NAME
93#define TARGET(NAME) EXPAND(NAME)
Brian Swetland2defe162009-08-18 14:35:59 -070094
Ajay Dudanicd01f9b2010-02-23 21:13:04 -080095#ifdef MEMBASE
96#define EMMC_BOOT_IMG_HEADER_ADDR (0xFF000+(MEMBASE))
97#else
David Ng183a7422009-12-07 14:55:21 -080098#define EMMC_BOOT_IMG_HEADER_ADDR 0xFF000
Ajay Dudanicd01f9b2010-02-23 21:13:04 -080099#endif
100
Deepa Dinamani0e163a42013-05-24 17:08:15 -0700101#ifndef MEMSIZE
102#define MEMSIZE 1024*1024
103#endif
104
105#define MAX_TAGS_SIZE 1024
106
Chandan Uddarajude85d3f2010-01-05 16:32:33 -0800107#define RECOVERY_MODE 0x77665502
108#define FASTBOOT_MODE 0x77665500
Matthew Qind886f3c2014-01-17 16:52:01 +0800109#define ALARM_BOOT 0x77665503
Chandan Uddarajude85d3f2010-01-05 16:32:33 -0800110
Kun Liang2f1601a2013-08-12 16:29:54 +0800111/* make 4096 as default size to ensure EFS,EXT4's erasing */
112#define DEFAULT_ERASE_SIZE 4096
Kuogee Hsieh55e92c52013-12-20 08:34:10 -0800113#define MAX_PANEL_BUF_SIZE 128
Kun Liang2f1601a2013-08-12 16:29:54 +0800114
Sundarajan Srinivasan595b71e2013-11-05 12:44:34 -0800115#define UBI_MAGIC "UBI#"
Dhaval Patelf83d73b2014-06-23 16:24:37 -0700116#define DISPLAY_DEFAULT_PREFIX "mdss_mdp"
Sundarajan Srinivasan595b71e2013-11-05 12:44:34 -0800117#define UBI_MAGIC_SIZE 0x04
Sundarajan Srinivasane52065a2014-03-20 16:25:59 -0700118#define BOOT_DEV_MAX_LEN 64
Sundarajan Srinivasan595b71e2013-11-05 12:44:34 -0800119
Abhimanyu Kapur0f79d572014-02-19 22:03:02 -0800120#define IS_ARM64(ptr) (ptr->magic_64 == KERNEL64_HDR_MAGIC) ? true : false
121
Channagoud Kadabifc3b31f2014-06-18 17:41:01 -0700122#define ADD_OF(a, b) (UINT_MAX - b > a) ? (a + b) : UINT_MAX
123
Smita Ghoshb4555da2014-09-18 14:14:56 -0700124#if UFS_SUPPORT || USE_BOOTDEV_CMDLINE
Sundarajan Srinivasane52065a2014-03-20 16:25:59 -0700125static const char *emmc_cmdline = " androidboot.bootdevice=";
Sundarajan Srinivasan3827a102013-09-10 13:57:40 -0700126#else
David Ng183a7422009-12-07 14:55:21 -0800127static const char *emmc_cmdline = " androidboot.emmc=true";
Sundarajan Srinivasan3827a102013-09-10 13:57:40 -0700128#endif
Subbaraman Narayanamurthyf17b4ae2011-02-16 20:19:56 -0800129static const char *usb_sn_cmdline = " androidboot.serialno=";
Pavel Nedev328ac822013-04-05 15:25:11 +0300130static const char *androidboot_mode = " androidboot.mode=";
Matthew Qind886f3c2014-01-17 16:52:01 +0800131static const char *alarmboot_cmdline = " androidboot.alarmboot=true";
Pavel Nedev898298c2013-02-27 12:36:09 -0800132static const char *loglevel = " quiet";
Ajay Dudanica3a33c2011-11-18 08:31:40 -0800133static const char *battchg_pause = " androidboot.mode=charger";
Shashank Mittalcd98d472011-08-02 14:29:24 -0700134static const char *auth_kernel = " androidboot.authorized_kernel=true";
Pavel Nedev5614d222013-06-17 18:01:02 +0300135static const char *secondary_gpt_enable = " gpt";
David Ng183a7422009-12-07 14:55:21 -0800136
Ajay Dudani6cff85e2011-02-04 16:02:16 -0800137static const char *baseband_apq = " androidboot.baseband=apq";
138static const char *baseband_msm = " androidboot.baseband=msm";
139static const char *baseband_csfb = " androidboot.baseband=csfb";
140static const char *baseband_svlte2a = " androidboot.baseband=svlte2a";
Ajay Dudani403bc492011-09-30 16:17:21 -0700141static const char *baseband_mdm = " androidboot.baseband=mdm";
Sundarajan Srinivasanaaa8aff2013-11-12 17:19:14 -0800142static const char *baseband_mdm2 = " androidboot.baseband=mdm2";
Amol Jadi5c61a952012-05-04 17:05:35 -0700143static const char *baseband_sglte = " androidboot.baseband=sglte";
Amol Jadi2a15a272013-01-22 12:03:36 -0800144static const char *baseband_dsda = " androidboot.baseband=dsda";
145static const char *baseband_dsda2 = " androidboot.baseband=dsda2";
sundarajan srinivasanf8e9f3f2013-03-04 15:56:58 -0800146static const char *baseband_sglte2 = " androidboot.baseband=sglte2";
Hanumant Singh8e1ac232014-01-29 13:41:51 -0800147static const char *warmboot_cmdline = " qpnp-power-on.warm_boot=1";
Ajay Dudanid04110c2011-01-17 23:55:07 -0800148
Deepa Dinamani41fa8d62013-05-23 13:25:36 -0700149static unsigned page_size = 0;
150static unsigned page_mask = 0;
151static char ffbm_mode_string[FFBM_MODE_BUF_SIZE];
152static bool boot_into_ffbm;
Joonwoo Park61112782013-10-02 19:50:39 -0700153static char target_boot_params[64];
Matthew Qind886f3c2014-01-17 16:52:01 +0800154static bool boot_reason_alarm;
Deepa Dinamani41fa8d62013-05-23 13:25:36 -0700155
Shashank Mittalcd98d472011-08-02 14:29:24 -0700156/* Assuming unauthorized kernel image by default */
157static int auth_kernel_img = 0;
158
Shashank Mittald3e54dd2014-08-28 15:24:02 -0700159static device_info device = {DEVICE_MAGIC, 0, 0, 0, 0, 0};
Shashank Mittal162244e2011-08-08 19:01:25 -0700160
Dima Zavin42168f22009-01-30 11:52:22 -0800161struct atag_ptbl_entry
162{
163 char name[16];
164 unsigned offset;
165 unsigned size;
166 unsigned flags;
167};
168
Channagoud Kadabi4c4884e2013-04-09 17:12:13 -0700169/*
170 * Partition info, required to be published
171 * for fastboot
172 */
173struct getvar_partition_info {
174 const char part_name[MAX_GPT_NAME_SIZE]; /* Partition name */
175 char getvar_size[MAX_GET_VAR_NAME_SIZE]; /* fastboot get var name for size */
176 char getvar_type[MAX_GET_VAR_NAME_SIZE]; /* fastboot get var name for type */
177 char size_response[MAX_RSP_SIZE]; /* fastboot response for size */
178 char type_response[MAX_RSP_SIZE]; /* fastboot response for type */
179};
180
181/*
182 * Right now, we are publishing the info for only
183 * three partitions
184 */
185struct getvar_partition_info part_info[] =
186{
187 { "system" , "partition-size:", "partition-type:", "", "ext4" },
188 { "userdata", "partition-size:", "partition-type:", "", "ext4" },
189 { "cache" , "partition-size:", "partition-type:", "", "ext4" },
190};
191
192char max_download_size[MAX_RSP_SIZE];
Ameya Thakur11cf1a62013-08-05 12:44:48 -0700193char charger_screen_enabled[MAX_RSP_SIZE];
Subbaraman Narayanamurthyf17b4ae2011-02-16 20:19:56 -0800194char sn_buf[13];
Dhaval Patel223ec952013-07-18 14:49:44 -0700195char display_panel_buf[MAX_PANEL_BUF_SIZE];
Unnati Gandhi62c8ab82014-01-24 11:01:01 +0530196char panel_display_mode[MAX_RSP_SIZE];
Greg Griscod6250552011-06-29 14:40:23 -0700197
Greg Griscod2471ef2011-07-14 13:00:42 -0700198extern int emmc_recovery_init(void);
199
Kinson Chik0b1c8162011-08-31 16:31:57 -0700200#if NO_KEYPAD_DRIVER
201extern int fastboot_trigger(void);
202#endif
Greg Griscod2471ef2011-07-14 13:00:42 -0700203
Abhimanyu Kapur0f79d572014-02-19 22:03:02 -0800204static void update_ker_tags_rdisk_addr(struct boot_img_hdr *hdr, bool is_arm64)
Channagoud Kadabia22144f2013-03-20 11:49:01 -0700205{
206 /* overwrite the destination of specified for the project */
Channagoud Kadabi7042fa32013-04-26 16:44:14 -0700207#ifdef ABOOT_IGNORE_BOOT_HEADER_ADDRS
Abhimanyu Kapur0f79d572014-02-19 22:03:02 -0800208 if (is_arm64)
209 hdr->kernel_addr = ABOOT_FORCE_KERNEL64_ADDR;
210 else
211 hdr->kernel_addr = ABOOT_FORCE_KERNEL_ADDR;
Channagoud Kadabi7042fa32013-04-26 16:44:14 -0700212 hdr->ramdisk_addr = ABOOT_FORCE_RAMDISK_ADDR;
213 hdr->tags_addr = ABOOT_FORCE_TAGS_ADDR;
Channagoud Kadabia22144f2013-03-20 11:49:01 -0700214#endif
215}
216
Dima Zavin42168f22009-01-30 11:52:22 -0800217static void ptentry_to_tag(unsigned **ptr, struct ptentry *ptn)
218{
219 struct atag_ptbl_entry atag_ptn;
220
221 memcpy(atag_ptn.name, ptn->name, 16);
222 atag_ptn.name[15] = '\0';
223 atag_ptn.offset = ptn->start;
224 atag_ptn.size = ptn->length;
225 atag_ptn.flags = ptn->flags;
226 memcpy(*ptr, &atag_ptn, sizeof(struct atag_ptbl_entry));
227 *ptr += sizeof(struct atag_ptbl_entry) / sizeof(unsigned);
228}
Brian Swetland9c4c0752009-01-25 16:23:50 -0800229
Neeti Desaie245d492012-06-01 12:52:13 -0700230unsigned char *update_cmdline(const char * cmdline)
Brian Swetland9c4c0752009-01-25 16:23:50 -0800231{
David Ng183a7422009-12-07 14:55:21 -0800232 int cmdline_len = 0;
233 int have_cmdline = 0;
Amol Jadi168b7712012-03-06 16:15:00 -0800234 unsigned char *cmdline_final = NULL;
Neeti Desaie245d492012-06-01 12:52:13 -0700235 int pause_at_bootup = 0;
Hanumant Singh8e1ac232014-01-29 13:41:51 -0800236 bool warm_boot = false;
Pavel Nedev5614d222013-06-17 18:01:02 +0300237 bool gpt_exists = partition_gpt_exists();
Joonwoo Park61112782013-10-02 19:50:39 -0700238 int have_target_boot_params = 0;
Sundarajan Srinivasane52065a2014-03-20 16:25:59 -0700239 char *boot_dev_buf = NULL;
Dima Zavin42168f22009-01-30 11:52:22 -0800240
Brian Swetland9c4c0752009-01-25 16:23:50 -0800241 if (cmdline && cmdline[0]) {
David Ng183a7422009-12-07 14:55:21 -0800242 cmdline_len = strlen(cmdline);
243 have_cmdline = 1;
244 }
245 if (target_is_emmc_boot()) {
246 cmdline_len += strlen(emmc_cmdline);
Smita Ghoshb4555da2014-09-18 14:14:56 -0700247#if UFS_SUPPORT || USE_BOOTDEV_CMDLINE
Sundarajan Srinivasane52065a2014-03-20 16:25:59 -0700248 boot_dev_buf = (char *) malloc(sizeof(char) * BOOT_DEV_MAX_LEN);
249 ASSERT(boot_dev_buf);
250 platform_boot_dev_cmdline(boot_dev_buf);
251 cmdline_len += strlen(boot_dev_buf);
Sundarajan Srinivasan3827a102013-09-10 13:57:40 -0700252#endif
David Ng183a7422009-12-07 14:55:21 -0800253 }
Subbaraman Narayanamurthyf17b4ae2011-02-16 20:19:56 -0800254
255 cmdline_len += strlen(usb_sn_cmdline);
256 cmdline_len += strlen(sn_buf);
257
Pavel Nedev5614d222013-06-17 18:01:02 +0300258 if (boot_into_recovery && gpt_exists)
259 cmdline_len += strlen(secondary_gpt_enable);
260
Pavel Nedev328ac822013-04-05 15:25:11 +0300261 if (boot_into_ffbm) {
262 cmdline_len += strlen(androidboot_mode);
Deepa Dinamani41fa8d62013-05-23 13:25:36 -0700263 cmdline_len += strlen(ffbm_mode_string);
Pavel Nedev898298c2013-02-27 12:36:09 -0800264 /* reduce kernel console messages to speed-up boot */
265 cmdline_len += strlen(loglevel);
Matthew Qind886f3c2014-01-17 16:52:01 +0800266 } else if (boot_reason_alarm) {
267 cmdline_len += strlen(alarmboot_cmdline);
Ameya Thakur11cf1a62013-08-05 12:44:48 -0700268 } else if (device.charger_screen_enabled &&
269 target_pause_for_battery_charge()) {
David Ngf773dde2010-07-26 19:55:08 -0700270 pause_at_bootup = 1;
271 cmdline_len += strlen(battchg_pause);
272 }
Ajay Dudanid04110c2011-01-17 23:55:07 -0800273
Shashank Mittalcd98d472011-08-02 14:29:24 -0700274 if(target_use_signed_kernel() && auth_kernel_img) {
275 cmdline_len += strlen(auth_kernel);
276 }
277
Joonwoo Park61112782013-10-02 19:50:39 -0700278 if (get_target_boot_params(cmdline, boot_into_recovery ? "recoveryfs" :
279 "system",
280 target_boot_params,
281 sizeof(target_boot_params)) == 0) {
282 have_target_boot_params = 1;
283 cmdline_len += strlen(target_boot_params);
284 }
285
Ajay Dudanid04110c2011-01-17 23:55:07 -0800286 /* Determine correct androidboot.baseband to use */
287 switch(target_baseband())
288 {
289 case BASEBAND_APQ:
290 cmdline_len += strlen(baseband_apq);
291 break;
292
293 case BASEBAND_MSM:
294 cmdline_len += strlen(baseband_msm);
295 break;
296
297 case BASEBAND_CSFB:
298 cmdline_len += strlen(baseband_csfb);
299 break;
300
Ajay Dudani6cff85e2011-02-04 16:02:16 -0800301 case BASEBAND_SVLTE2A:
302 cmdline_len += strlen(baseband_svlte2a);
Ajay Dudanid04110c2011-01-17 23:55:07 -0800303 break;
Ajay Dudani403bc492011-09-30 16:17:21 -0700304
305 case BASEBAND_MDM:
306 cmdline_len += strlen(baseband_mdm);
307 break;
Amol Jadi5c61a952012-05-04 17:05:35 -0700308
Sundarajan Srinivasanaaa8aff2013-11-12 17:19:14 -0800309 case BASEBAND_MDM2:
310 cmdline_len += strlen(baseband_mdm2);
311 break;
312
Amol Jadi5c61a952012-05-04 17:05:35 -0700313 case BASEBAND_SGLTE:
314 cmdline_len += strlen(baseband_sglte);
315 break;
Channagoud Kadabi141f2982012-10-31 11:23:02 +0530316
sundarajan srinivasanf8e9f3f2013-03-04 15:56:58 -0800317 case BASEBAND_SGLTE2:
318 cmdline_len += strlen(baseband_sglte2);
319 break;
320
Channagoud Kadabi141f2982012-10-31 11:23:02 +0530321 case BASEBAND_DSDA:
322 cmdline_len += strlen(baseband_dsda);
323 break;
Amol Jadi2a15a272013-01-22 12:03:36 -0800324
325 case BASEBAND_DSDA2:
326 cmdline_len += strlen(baseband_dsda2);
327 break;
Ajay Dudanid04110c2011-01-17 23:55:07 -0800328 }
329
Lijuan Gao4a5b8322014-07-24 10:38:42 +0800330 if (cmdline) {
331 if ((strstr(cmdline, DISPLAY_DEFAULT_PREFIX) == NULL) &&
332 target_display_panel_node(device.display_panel,
333 display_panel_buf, MAX_PANEL_BUF_SIZE) &&
334 strlen(display_panel_buf)) {
335 cmdline_len += strlen(display_panel_buf);
336 }
Dhaval Patel223ec952013-07-18 14:49:44 -0700337 }
338
Hanumant Singh8e1ac232014-01-29 13:41:51 -0800339 if (target_warm_boot()) {
340 warm_boot = true;
341 cmdline_len += strlen(warmboot_cmdline);
342 }
343
David Ng183a7422009-12-07 14:55:21 -0800344 if (cmdline_len > 0) {
345 const char *src;
Maria Yu52254c02014-07-04 16:14:54 +0800346 unsigned char *dst;
347
348 cmdline_final = (unsigned char*) malloc((cmdline_len + 4) & (~3));
349 ASSERT(cmdline_final != NULL);
350 dst = cmdline_final;
Neeti Desaie245d492012-06-01 12:52:13 -0700351
Amol Jadi168b7712012-03-06 16:15:00 -0800352 /* Save start ptr for debug print */
David Ng183a7422009-12-07 14:55:21 -0800353 if (have_cmdline) {
354 src = cmdline;
355 while ((*dst++ = *src++));
356 }
357 if (target_is_emmc_boot()) {
358 src = emmc_cmdline;
359 if (have_cmdline) --dst;
David Ngf773dde2010-07-26 19:55:08 -0700360 have_cmdline = 1;
361 while ((*dst++ = *src++));
Smita Ghoshb4555da2014-09-18 14:14:56 -0700362#if UFS_SUPPORT || USE_BOOTDEV_CMDLINE
Sundarajan Srinivasane52065a2014-03-20 16:25:59 -0700363 src = boot_dev_buf;
364 if (have_cmdline) --dst;
365 while ((*dst++ = *src++));
366#endif
David Ngf773dde2010-07-26 19:55:08 -0700367 }
Subbaraman Narayanamurthyf17b4ae2011-02-16 20:19:56 -0800368
369 src = usb_sn_cmdline;
370 if (have_cmdline) --dst;
371 have_cmdline = 1;
372 while ((*dst++ = *src++));
373 src = sn_buf;
374 if (have_cmdline) --dst;
375 have_cmdline = 1;
376 while ((*dst++ = *src++));
Hanumant Singh8e1ac232014-01-29 13:41:51 -0800377 if (warm_boot) {
378 if (have_cmdline) --dst;
379 src = warmboot_cmdline;
380 while ((*dst++ = *src++));
381 }
Subbaraman Narayanamurthyf17b4ae2011-02-16 20:19:56 -0800382
Pavel Nedev5614d222013-06-17 18:01:02 +0300383 if (boot_into_recovery && gpt_exists) {
384 src = secondary_gpt_enable;
385 if (have_cmdline) --dst;
386 while ((*dst++ = *src++));
387 }
388
Pavel Nedev328ac822013-04-05 15:25:11 +0300389 if (boot_into_ffbm) {
390 src = androidboot_mode;
391 if (have_cmdline) --dst;
392 while ((*dst++ = *src++));
Deepa Dinamani41fa8d62013-05-23 13:25:36 -0700393 src = ffbm_mode_string;
Pavel Nedev328ac822013-04-05 15:25:11 +0300394 if (have_cmdline) --dst;
395 while ((*dst++ = *src++));
Pavel Nedev898298c2013-02-27 12:36:09 -0800396 src = loglevel;
397 if (have_cmdline) --dst;
398 while ((*dst++ = *src++));
Matthew Qind886f3c2014-01-17 16:52:01 +0800399 } else if (boot_reason_alarm) {
400 src = alarmboot_cmdline;
401 if (have_cmdline) --dst;
402 while ((*dst++ = *src++));
Pavel Nedev328ac822013-04-05 15:25:11 +0300403 } else if (pause_at_bootup) {
David Ngf773dde2010-07-26 19:55:08 -0700404 src = battchg_pause;
405 if (have_cmdline) --dst;
David Ng183a7422009-12-07 14:55:21 -0800406 while ((*dst++ = *src++));
407 }
Ajay Dudanid04110c2011-01-17 23:55:07 -0800408
Shashank Mittalcd98d472011-08-02 14:29:24 -0700409 if(target_use_signed_kernel() && auth_kernel_img) {
410 src = auth_kernel;
411 if (have_cmdline) --dst;
412 while ((*dst++ = *src++));
413 }
414
Ajay Dudanid04110c2011-01-17 23:55:07 -0800415 switch(target_baseband())
416 {
417 case BASEBAND_APQ:
418 src = baseband_apq;
419 if (have_cmdline) --dst;
420 while ((*dst++ = *src++));
421 break;
422
423 case BASEBAND_MSM:
424 src = baseband_msm;
425 if (have_cmdline) --dst;
426 while ((*dst++ = *src++));
427 break;
428
429 case BASEBAND_CSFB:
430 src = baseband_csfb;
431 if (have_cmdline) --dst;
432 while ((*dst++ = *src++));
433 break;
434
Ajay Dudani6cff85e2011-02-04 16:02:16 -0800435 case BASEBAND_SVLTE2A:
436 src = baseband_svlte2a;
Ajay Dudanid04110c2011-01-17 23:55:07 -0800437 if (have_cmdline) --dst;
438 while ((*dst++ = *src++));
439 break;
Ajay Dudani403bc492011-09-30 16:17:21 -0700440
441 case BASEBAND_MDM:
442 src = baseband_mdm;
443 if (have_cmdline) --dst;
444 while ((*dst++ = *src++));
445 break;
Amol Jadi5c61a952012-05-04 17:05:35 -0700446
Sundarajan Srinivasanaaa8aff2013-11-12 17:19:14 -0800447 case BASEBAND_MDM2:
448 src = baseband_mdm2;
449 if (have_cmdline) --dst;
450 while ((*dst++ = *src++));
451 break;
452
Amol Jadi5c61a952012-05-04 17:05:35 -0700453 case BASEBAND_SGLTE:
454 src = baseband_sglte;
455 if (have_cmdline) --dst;
456 while ((*dst++ = *src++));
457 break;
Channagoud Kadabi141f2982012-10-31 11:23:02 +0530458
sundarajan srinivasanf8e9f3f2013-03-04 15:56:58 -0800459 case BASEBAND_SGLTE2:
460 src = baseband_sglte2;
461 if (have_cmdline) --dst;
462 while ((*dst++ = *src++));
463 break;
464
Channagoud Kadabi141f2982012-10-31 11:23:02 +0530465 case BASEBAND_DSDA:
466 src = baseband_dsda;
467 if (have_cmdline) --dst;
468 while ((*dst++ = *src++));
469 break;
Amol Jadi2a15a272013-01-22 12:03:36 -0800470
471 case BASEBAND_DSDA2:
472 src = baseband_dsda2;
473 if (have_cmdline) --dst;
474 while ((*dst++ = *src++));
475 break;
Ajay Dudanid04110c2011-01-17 23:55:07 -0800476 }
Dhaval Patel223ec952013-07-18 14:49:44 -0700477
478 if (strlen(display_panel_buf)) {
Dhaval Patel223ec952013-07-18 14:49:44 -0700479 src = display_panel_buf;
480 if (have_cmdline) --dst;
481 while ((*dst++ = *src++));
482 }
Joonwoo Park61112782013-10-02 19:50:39 -0700483
484 if (have_target_boot_params) {
485 if (have_cmdline) --dst;
486 src = target_boot_params;
487 while ((*dst++ = *src++));
488 }
Neeti Desaie245d492012-06-01 12:52:13 -0700489 }
Dhaval Patel223ec952013-07-18 14:49:44 -0700490
491
Sundarajan Srinivasane52065a2014-03-20 16:25:59 -0700492 if (boot_dev_buf)
493 free(boot_dev_buf);
494
Maria Yu9ca0c402014-07-07 14:49:34 +0800495 dprintf(INFO, "cmdline: %s\n", cmdline_final ? cmdline_final : "");
Neeti Desaie245d492012-06-01 12:52:13 -0700496 return cmdline_final;
497}
498
499unsigned *atag_core(unsigned *ptr)
500{
501 /* CORE */
502 *ptr++ = 2;
503 *ptr++ = 0x54410001;
504
505 return ptr;
506
507}
508
509unsigned *atag_ramdisk(unsigned *ptr, void *ramdisk,
510 unsigned ramdisk_size)
511{
512 if (ramdisk_size) {
513 *ptr++ = 4;
514 *ptr++ = 0x54420005;
515 *ptr++ = (unsigned)ramdisk;
516 *ptr++ = ramdisk_size;
Brian Swetland9c4c0752009-01-25 16:23:50 -0800517 }
518
Neeti Desaie245d492012-06-01 12:52:13 -0700519 return ptr;
520}
521
522unsigned *atag_ptable(unsigned **ptr_addr)
523{
524 int i;
525 struct ptable *ptable;
526
527 if ((ptable = flash_get_ptable()) && (ptable->count != 0)) {
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -0700528 *(*ptr_addr)++ = 2 + (ptable->count * (sizeof(struct atag_ptbl_entry) /
529 sizeof(unsigned)));
Neeti Desaie245d492012-06-01 12:52:13 -0700530 *(*ptr_addr)++ = 0x4d534d70;
531 for (i = 0; i < ptable->count; ++i)
532 ptentry_to_tag(ptr_addr, ptable_get(ptable, i));
533 }
534
535 return (*ptr_addr);
536}
537
538unsigned *atag_cmdline(unsigned *ptr, const char *cmdline)
539{
540 int cmdline_length = 0;
541 int n;
Neeti Desaie245d492012-06-01 12:52:13 -0700542 char *dest;
543
Amol Jadi10c7d1c2013-01-25 13:24:29 -0800544 cmdline_length = strlen((const char*)cmdline);
Neeti Desaie245d492012-06-01 12:52:13 -0700545 n = (cmdline_length + 4) & (~3);
546
547 *ptr++ = (n / 4) + 2;
548 *ptr++ = 0x54410009;
549 dest = (char *) ptr;
Amol Jadi10c7d1c2013-01-25 13:24:29 -0800550 while ((*dest++ = *cmdline++));
Neeti Desaie245d492012-06-01 12:52:13 -0700551 ptr += (n / 4);
552
553 return ptr;
554}
555
556unsigned *atag_end(unsigned *ptr)
557{
Brian Swetland9c4c0752009-01-25 16:23:50 -0800558 /* END */
559 *ptr++ = 0;
560 *ptr++ = 0;
561
Neeti Desaie245d492012-06-01 12:52:13 -0700562 return ptr;
563}
564
565void generate_atags(unsigned *ptr, const char *cmdline,
566 void *ramdisk, unsigned ramdisk_size)
567{
568
569 ptr = atag_core(ptr);
570 ptr = atag_ramdisk(ptr, ramdisk, ramdisk_size);
571 ptr = target_atag_mem(ptr);
572
573 /* Skip NAND partition ATAGS for eMMC boot */
574 if (!target_is_emmc_boot()){
575 ptr = atag_ptable(&ptr);
576 }
577
578 ptr = atag_cmdline(ptr, cmdline);
579 ptr = atag_end(ptr);
580}
581
Deepa Dinamani0bf2f442012-10-19 11:41:06 -0700582typedef void entry_func_ptr(unsigned, unsigned, unsigned*);
Neeti Desaie245d492012-06-01 12:52:13 -0700583void boot_linux(void *kernel, unsigned *tags,
584 const char *cmdline, unsigned machtype,
585 void *ramdisk, unsigned ramdisk_size)
586{
Amol Jadi10c7d1c2013-01-25 13:24:29 -0800587 unsigned char *final_cmdline;
Amol Jadib6be5c12012-11-14 13:39:51 -0800588#if DEVICE_TREE
Neeti Desai17379b82012-06-04 18:42:53 -0700589 int ret = 0;
Amol Jadib6be5c12012-11-14 13:39:51 -0800590#endif
591
Deepa Dinamani0bf2f442012-10-19 11:41:06 -0700592 void (*entry)(unsigned, unsigned, unsigned*) = (entry_func_ptr*)(PA((addr_t)kernel));
Deepa Dinamani25a9f762012-11-30 15:57:15 -0800593 uint32_t tags_phys = PA((addr_t)tags);
Abhimanyu Kapur0f79d572014-02-19 22:03:02 -0800594 struct kernel64_hdr *kptr = (struct kernel64_hdr*)kernel;
Deepa Dinamani25a9f762012-11-30 15:57:15 -0800595
596 ramdisk = PA(ramdisk);
Neeti Desaie245d492012-06-01 12:52:13 -0700597
Amol Jadi10c7d1c2013-01-25 13:24:29 -0800598 final_cmdline = update_cmdline((const char*)cmdline);
599
Neeti Desai17379b82012-06-04 18:42:53 -0700600#if DEVICE_TREE
Amol Jadib6be5c12012-11-14 13:39:51 -0800601 dprintf(INFO, "Updating device tree: start\n");
602
Neeti Desai17379b82012-06-04 18:42:53 -0700603 /* Update the Device Tree */
Amol Jadi10c7d1c2013-01-25 13:24:29 -0800604 ret = update_device_tree((void *)tags, final_cmdline, ramdisk, ramdisk_size);
Neeti Desai17379b82012-06-04 18:42:53 -0700605 if(ret)
606 {
607 dprintf(CRITICAL, "ERROR: Updating Device Tree Failed \n");
608 ASSERT(0);
609 }
Amol Jadib6be5c12012-11-14 13:39:51 -0800610 dprintf(INFO, "Updating device tree: done\n");
Neeti Desai17379b82012-06-04 18:42:53 -0700611#else
Neeti Desaie245d492012-06-01 12:52:13 -0700612 /* Generating the Atags */
Amol Jadi10c7d1c2013-01-25 13:24:29 -0800613 generate_atags(tags, final_cmdline, ramdisk, ramdisk_size);
Neeti Desai17379b82012-06-04 18:42:53 -0700614#endif
Neeti Desaie245d492012-06-01 12:52:13 -0700615
Maria Yu52254c02014-07-04 16:14:54 +0800616 free(final_cmdline);
Channagoud Kadabi5d0371c2014-10-21 22:27:07 -0700617
618#if VERIFIED_BOOT
619 /* Write protect the device info */
620 if (mmc_write_protect("devinfo", 1))
621 {
622 dprintf(INFO, "Failed to write protect dev info\n");
623 ASSERT(0);
624 }
625#endif
626
Channagoud Kadabi33defe22013-06-18 18:35:40 -0700627 /* Perform target specific cleanup */
628 target_uninit();
629
Aravind Venkateswaran8f076242014-02-25 16:25:30 -0800630 /* Turn off splash screen if enabled */
631#if DISPLAY_SPLASH_SCREEN
632 target_display_shutdown();
633#endif
634
635
Deepa Dinamani33734bc2013-03-06 12:16:06 -0800636 dprintf(INFO, "booting linux @ %p, ramdisk @ %p (%d), tags/device tree @ %p\n",
637 entry, ramdisk, ramdisk_size, tags_phys);
Brian Swetland9c4c0752009-01-25 16:23:50 -0800638
639 enter_critical_section();
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -0700640
Amol Jadi4421e652011-06-16 15:00:48 -0700641 /* do any platform specific cleanup before kernel entry */
642 platform_uninit();
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -0700643
Brian Swetland9c4c0752009-01-25 16:23:50 -0800644 arch_disable_cache(UCACHE);
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -0700645
Amol Jadi504f9fe2012-08-16 13:56:48 -0700646#if ARM_WITH_MMU
Brian Swetland9c4c0752009-01-25 16:23:50 -0800647 arch_disable_mmu();
Amol Jadi504f9fe2012-08-16 13:56:48 -0700648#endif
Amol Jadi492d5a52013-03-15 16:12:34 -0700649 bs_set_timestamp(BS_KERNEL_ENTRY);
Abhimanyu Kapur0f79d572014-02-19 22:03:02 -0800650
651 if (IS_ARM64(kptr))
652 /* Jump to a 64bit kernel */
653 scm_elexec_call((paddr_t)kernel, tags_phys);
654 else
655 /* Jump to a 32bit kernel */
656 entry(0, machtype, (unsigned*)tags_phys);
Brian Swetland9c4c0752009-01-25 16:23:50 -0800657}
658
Deepa Dinamani0e163a42013-05-24 17:08:15 -0700659/* Function to check if the memory address range falls within the aboot
660 * boundaries.
661 * start: Start of the memory region
662 * size: Size of the memory region
663 */
664int check_aboot_addr_range_overlap(uint32_t start, uint32_t size)
665{
666 /* Check for boundary conditions. */
Sundarajan Srinivasance2a0ea2013-12-16 17:02:56 -0800667 if ((UINT_MAX - start) < size)
Deepa Dinamani0e163a42013-05-24 17:08:15 -0700668 return -1;
669
670 /* Check for memory overlap. */
671 if ((start < MEMBASE) && ((start + size) <= MEMBASE))
672 return 0;
Channagoud Kadabi94143912013-10-15 12:53:52 -0700673 else if (start >= (MEMBASE + MEMSIZE))
Deepa Dinamani0e163a42013-05-24 17:08:15 -0700674 return 0;
675 else
676 return -1;
677}
678
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800679#define ROUND_TO_PAGE(x,y) (((x) + (y)) & (~(y)))
Brian Swetland9c4c0752009-01-25 16:23:50 -0800680
Abhimanyu Kapur0f79d572014-02-19 22:03:02 -0800681BUF_DMA_ALIGN(buf, BOOT_IMG_MAX_PAGE_SIZE); //Equal to max-supported pagesize
Amol Jadib6be5c12012-11-14 13:39:51 -0800682#if DEVICE_TREE
Abhimanyu Kapur0f79d572014-02-19 22:03:02 -0800683BUF_DMA_ALIGN(dt_buf, BOOT_IMG_MAX_PAGE_SIZE);
Amol Jadib6be5c12012-11-14 13:39:51 -0800684#endif
Dima Zavin214cc642009-01-26 11:16:21 -0800685
Deepa Dinamani0e163a42013-05-24 17:08:15 -0700686static void verify_signed_bootimg(uint32_t bootimg_addr, uint32_t bootimg_size)
687{
688 int ret;
Sundarajan Srinivasance54d6e2013-11-11 12:45:00 -0800689#if IMAGE_VERIF_ALGO_SHA1
690 uint32_t auth_algo = CRYPTO_AUTH_ALG_SHA1;
691#else
692 uint32_t auth_algo = CRYPTO_AUTH_ALG_SHA256;
693#endif
Deepa Dinamani0e163a42013-05-24 17:08:15 -0700694
695 /* Assume device is rooted at this time. */
696 device.is_tampered = 1;
697
698 dprintf(INFO, "Authenticating boot image (%d): start\n", bootimg_size);
699
Shashank Mittald3e54dd2014-08-28 15:24:02 -0700700#if VERIFIED_BOOT
701 if(boot_into_recovery)
702 {
703 ret = boot_verify_image((unsigned char *)bootimg_addr,
704 bootimg_size, "recovery");
705 }
706 else
707 {
708 ret = boot_verify_image((unsigned char *)bootimg_addr,
709 bootimg_size, "boot");
710 }
711 boot_verify_print_state();
712#else
Deepa Dinamani0e163a42013-05-24 17:08:15 -0700713 ret = image_verify((unsigned char *)bootimg_addr,
714 (unsigned char *)(bootimg_addr + bootimg_size),
715 bootimg_size,
Sundarajan Srinivasance54d6e2013-11-11 12:45:00 -0800716 auth_algo);
Shashank Mittald3e54dd2014-08-28 15:24:02 -0700717#endif
Deepa Dinamani0e163a42013-05-24 17:08:15 -0700718 dprintf(INFO, "Authenticating boot image: done return value = %d\n", ret);
719
720 if (ret)
721 {
722 /* Authorized kernel */
723 device.is_tampered = 0;
Sundarajan Srinivasan3fb21f12013-09-16 18:36:15 -0700724 auth_kernel_img = 1;
Deepa Dinamani0e163a42013-05-24 17:08:15 -0700725 }
726
727#if USE_PCOM_SECBOOT
728 set_tamper_flag(device.is_tampered);
729#endif
730
731 if(device.is_tampered)
732 {
733 write_device_info_mmc(&device);
734 #ifdef TZ_TAMPER_FUSE
735 set_tamper_fuse_cmd();
736 #endif
737 #ifdef ASSERT_ON_TAMPER
738 dprintf(CRITICAL, "Device is tampered. Asserting..\n");
739 ASSERT(0);
740 #endif
741 }
Shashank Mittald3e54dd2014-08-28 15:24:02 -0700742
743#if VERIFIED_BOOT
744 if(boot_verify_get_state() == RED)
745 {
746 if(!boot_into_recovery)
747 {
748 dprintf(CRITICAL,
749 "Device verification failed. Rebooting into recovery.\n");
750 reboot_device(RECOVERY_MODE);
751 }
752 else
753 {
754 dprintf(CRITICAL,
755 "Recovery image verification failed. Asserting..\n");
756 ASSERT(0);
757 }
758 }
759#endif
Deepa Dinamani0e163a42013-05-24 17:08:15 -0700760}
761
Maunik Shah0f3c8ac2014-03-02 17:47:58 +0530762static bool check_format_bit()
763{
764 bool ret = false;
765 int index;
766 uint64_t offset;
767 struct boot_selection_info *in = NULL;
768 char *buf = NULL;
769
770 index = partition_get_index("bootselect");
771 if (index == INVALID_PTN)
772 {
773 dprintf(INFO, "Unable to locate /bootselect partition\n");
774 return ret;
775 }
776 offset = partition_get_offset(index);
777 if(!offset)
778 {
779 dprintf(INFO, "partition /bootselect doesn't exist\n");
780 return ret;
781 }
782 buf = (char *) memalign(CACHE_LINE, ROUNDUP(page_size, CACHE_LINE));
783 ASSERT(buf);
784 if (mmc_read(offset, (unsigned int *)buf, page_size))
785 {
786 dprintf(INFO, "mmc read failure /bootselect %d\n", page_size);
787 free(buf);
788 return ret;
789 }
790 in = (struct boot_selection_info *) buf;
791 if ((in->signature == BOOTSELECT_SIGNATURE) &&
792 (in->version == BOOTSELECT_VERSION)) {
793 if ((in->state_info & BOOTSELECT_FORMAT) &&
794 !(in->state_info & BOOTSELECT_FACTORY))
795 ret = true;
796 } else {
797 dprintf(CRITICAL, "Signature: 0x%08x or version: 0x%08x mismatched of /bootselect\n",
798 in->signature, in->version);
799 ASSERT(0);
800 }
801 free(buf);
802 return ret;
803}
804
Shashank Mittald3e54dd2014-08-28 15:24:02 -0700805void boot_verifier_init()
806{
807
808 uint32_t boot_state;
809 /* Check if device unlock */
810 if(device.is_unlocked)
811 {
812 boot_verify_send_event(DEV_UNLOCK);
813 boot_verify_print_state();
814 dprintf(CRITICAL, "Device is unlocked! Skipping verification...\n");
815 return;
816 }
817 else
818 {
819 boot_verify_send_event(BOOT_INIT);
820 }
821
822 /* Initialize keystore */
823 boot_state = boot_verify_keystore_init();
824 if(boot_state == YELLOW)
825 {
826 boot_verify_print_state();
827 dprintf(CRITICAL, "Keystore verification failed! Continuing anyways...\n");
828 }
829}
830
Shashank Mittal23b8f422010-04-16 19:27:21 -0700831int boot_linux_from_mmc(void)
832{
833 struct boot_img_hdr *hdr = (void*) buf;
834 struct boot_img_hdr *uhdr;
835 unsigned offset = 0;
Deepa Dinamani41fa8d62013-05-23 13:25:36 -0700836 int rcode;
Shashank Mittal23b8f422010-04-16 19:27:21 -0700837 unsigned long long ptn = 0;
Kinson Chikf1a43512011-07-14 11:28:39 -0700838 int index = INVALID_PTN;
Shashank Mittal23b8f422010-04-16 19:27:21 -0700839
Shashank Mittalcd98d472011-08-02 14:29:24 -0700840 unsigned char *image_addr = 0;
841 unsigned kernel_actual;
842 unsigned ramdisk_actual;
843 unsigned imagesize_actual;
Neeti Desai465491e2012-07-31 12:53:35 -0700844 unsigned second_actual = 0;
Neeti Desai465491e2012-07-31 12:53:35 -0700845
846#if DEVICE_TREE
847 struct dt_table *table;
Joel Kingaa335dc2013-06-03 16:11:08 -0700848 struct dt_entry dt_entry;
Neeti Desai465491e2012-07-31 12:53:35 -0700849 unsigned dt_table_offset;
Deepa Dinamani7aaf83d2012-12-21 11:27:01 -0800850 uint32_t dt_actual;
Deepa Dinamani19648b42013-09-05 17:05:55 -0700851 uint32_t dt_hdr_size;
Neeti Desai465491e2012-07-31 12:53:35 -0700852#endif
Abhimanyu Kapur0f79d572014-02-19 22:03:02 -0800853 BUF_DMA_ALIGN(kbuf, BOOT_IMG_MAX_PAGE_SIZE);
854 struct kernel64_hdr *kptr = (void*) kbuf;
855
Maunik Shah0f3c8ac2014-03-02 17:47:58 +0530856 if (check_format_bit())
857 boot_into_recovery = 1;
858
Deepa Dinamani41fa8d62013-05-23 13:25:36 -0700859 if (!boot_into_recovery) {
860 memset(ffbm_mode_string, '\0', sizeof(ffbm_mode_string));
861 rcode = get_ffbm(ffbm_mode_string, sizeof(ffbm_mode_string));
862 if (rcode <= 0) {
863 boot_into_ffbm = false;
864 if (rcode < 0)
865 dprintf(CRITICAL,"failed to get ffbm cookie");
866 } else
867 boot_into_ffbm = true;
868 } else
869 boot_into_ffbm = false;
Shashank Mittal23b8f422010-04-16 19:27:21 -0700870 uhdr = (struct boot_img_hdr *)EMMC_BOOT_IMG_HEADER_ADDR;
871 if (!memcmp(uhdr->magic, BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
872 dprintf(INFO, "Unified boot method!\n");
873 hdr = uhdr;
874 goto unified_boot;
875 }
Greg Griscod6250552011-06-29 14:40:23 -0700876 if (!boot_into_recovery) {
Kinson Chikf1a43512011-07-14 11:28:39 -0700877 index = partition_get_index("boot");
878 ptn = partition_get_offset(index);
879 if(ptn == 0) {
Shashank Mittal85b91f62010-10-30 10:12:38 -0700880 dprintf(CRITICAL, "ERROR: No boot partition found\n");
881 return -1;
882 }
Kinson Chikf1a43512011-07-14 11:28:39 -0700883 }
884 else {
885 index = partition_get_index("recovery");
886 ptn = partition_get_offset(index);
887 if(ptn == 0) {
Shashank Mittal85b91f62010-10-30 10:12:38 -0700888 dprintf(CRITICAL, "ERROR: No recovery partition found\n");
889 return -1;
890 }
Shashank Mittal23b8f422010-04-16 19:27:21 -0700891 }
892
Greg Griscod6250552011-06-29 14:40:23 -0700893 if (mmc_read(ptn + offset, (unsigned int *) buf, page_size)) {
Shashank Mittal23b8f422010-04-16 19:27:21 -0700894 dprintf(CRITICAL, "ERROR: Cannot read boot image header\n");
895 return -1;
896 }
Shashank Mittal23b8f422010-04-16 19:27:21 -0700897
898 if (memcmp(hdr->magic, BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
Kinson Chik kchik@codeaurora.org82e4ae62011-04-12 17:42:07 -0700899 dprintf(CRITICAL, "ERROR: Invalid boot image header\n");
Shashank Mittal23b8f422010-04-16 19:27:21 -0700900 return -1;
901 }
902
Subbaraman Narayanamurthyfbe13a02010-09-10 11:51:12 -0700903 if (hdr->page_size && (hdr->page_size != page_size)) {
vijay kumar2e21b3a2014-06-26 17:40:15 +0530904
905 if (hdr->page_size > BOOT_IMG_MAX_PAGE_SIZE) {
906 dprintf(CRITICAL, "ERROR: Invalid page size\n");
907 return -1;
908 }
Subbaraman Narayanamurthyfbe13a02010-09-10 11:51:12 -0700909 page_size = hdr->page_size;
910 page_mask = page_size - 1;
Shashank Mittal23b8f422010-04-16 19:27:21 -0700911 }
912
Abhimanyu Kapur0f79d572014-02-19 22:03:02 -0800913 /* Read the next page to get kernel Image header
914 * which lives in the second page for arm64 targets.
915 */
916
917 if (mmc_read(ptn + page_size, (unsigned int *) kbuf, page_size)) {
918 dprintf(CRITICAL, "ERROR: Cannot read boot image header\n");
919 return -1;
920 }
921
Channagoud Kadabia22144f2013-03-20 11:49:01 -0700922 /*
923 * Update the kernel/ramdisk/tags address if the boot image header
924 * has default values, these default values come from mkbootimg when
925 * the boot image is flashed using fastboot flash:raw
926 */
Abhimanyu Kapur0f79d572014-02-19 22:03:02 -0800927 update_ker_tags_rdisk_addr(hdr, IS_ARM64(kptr));
Channagoud Kadabia22144f2013-03-20 11:49:01 -0700928
Deepa Dinamani0bf2f442012-10-19 11:41:06 -0700929 /* Get virtual addresses since the hdr saves physical addresses. */
930 hdr->kernel_addr = VA((addr_t)(hdr->kernel_addr));
931 hdr->ramdisk_addr = VA((addr_t)(hdr->ramdisk_addr));
932 hdr->tags_addr = VA((addr_t)(hdr->tags_addr));
Deepa Dinamani0e163a42013-05-24 17:08:15 -0700933
934 kernel_actual = ROUND_TO_PAGE(hdr->kernel_size, page_mask);
935 ramdisk_actual = ROUND_TO_PAGE(hdr->ramdisk_size, page_mask);
936
937 /* Check if the addresses in the header are valid. */
938 if (check_aboot_addr_range_overlap(hdr->kernel_addr, kernel_actual) ||
939 check_aboot_addr_range_overlap(hdr->ramdisk_addr, ramdisk_actual))
940 {
941 dprintf(CRITICAL, "kernel/ramdisk addresses overlap with aboot addresses.\n");
942 return -1;
943 }
944
945#ifndef DEVICE_TREE
946 if (check_aboot_addr_range_overlap(hdr->tags_addr, MAX_TAGS_SIZE))
947 {
948 dprintf(CRITICAL, "Tags addresses overlap with aboot addresses.\n");
949 return -1;
950 }
951#endif
952
Shashank Mittalcd98d472011-08-02 14:29:24 -0700953 /* Authenticate Kernel */
Amir Samuelov57a6fa22013-06-05 16:36:43 +0300954 dprintf(INFO, "use_signed_kernel=%d, is_unlocked=%d, is_tampered=%d.\n",
955 (int) target_use_signed_kernel(),
956 device.is_unlocked,
957 device.is_tampered);
958
Shashank Mittald3e54dd2014-08-28 15:24:02 -0700959#if VERIFIED_BOOT
960 boot_verifier_init();
961#endif
962
Deepa Dinamani23b60d42013-06-24 18:10:52 -0700963 if(target_use_signed_kernel() && (!device.is_unlocked))
Subbaraman Narayanamurthy958fa242011-01-27 17:42:38 -0800964 {
Deepa Dinamani0e163a42013-05-24 17:08:15 -0700965 offset = 0;
966
Shashank Mittalcd98d472011-08-02 14:29:24 -0700967 image_addr = (unsigned char *)target_get_scratch_address();
Deepa Dinamani0e163a42013-05-24 17:08:15 -0700968
Deepa Dinamani7aaf83d2012-12-21 11:27:01 -0800969#if DEVICE_TREE
970 dt_actual = ROUND_TO_PAGE(hdr->dt_size, page_mask);
971 imagesize_actual = (page_size + kernel_actual + ramdisk_actual + dt_actual);
Deepa Dinamani0e163a42013-05-24 17:08:15 -0700972
Deepa Dinamanid14bb4d2013-07-12 17:28:29 -0700973 if (check_aboot_addr_range_overlap(hdr->tags_addr, dt_actual))
Deepa Dinamani0e163a42013-05-24 17:08:15 -0700974 {
975 dprintf(CRITICAL, "Device tree addresses overlap with aboot addresses.\n");
976 return -1;
977 }
Deepa Dinamani7aaf83d2012-12-21 11:27:01 -0800978#else
Channagoud Kadabi4b276512012-08-28 15:16:30 +0530979 imagesize_actual = (page_size + kernel_actual + ramdisk_actual);
Shashank Mittal162244e2011-08-08 19:01:25 -0700980
Deepa Dinamani0e163a42013-05-24 17:08:15 -0700981#endif
Shashank Mittal162244e2011-08-08 19:01:25 -0700982
Amol Jadib6be5c12012-11-14 13:39:51 -0800983 dprintf(INFO, "Loading boot image (%d): start\n", imagesize_actual);
Amol Jadi492d5a52013-03-15 16:12:34 -0700984 bs_set_timestamp(BS_KERNEL_LOAD_START);
Amol Jadib6be5c12012-11-14 13:39:51 -0800985
Deepa Dinamanid14bb4d2013-07-12 17:28:29 -0700986 if (check_aboot_addr_range_overlap(image_addr, imagesize_actual))
987 {
988 dprintf(CRITICAL, "Boot image buffer address overlaps with aboot addresses.\n");
989 return -1;
990 }
991
Shashank Mittalcd98d472011-08-02 14:29:24 -0700992 /* Read image without signature */
993 if (mmc_read(ptn + offset, (void *)image_addr, imagesize_actual))
994 {
995 dprintf(CRITICAL, "ERROR: Cannot read boot image\n");
996 return -1;
Subbaraman Narayanamurthy958fa242011-01-27 17:42:38 -0800997 }
Shashank Mittalcd98d472011-08-02 14:29:24 -0700998
Amol Jadib6be5c12012-11-14 13:39:51 -0800999 dprintf(INFO, "Loading boot image (%d): done\n", imagesize_actual);
Amol Jadi492d5a52013-03-15 16:12:34 -07001000 bs_set_timestamp(BS_KERNEL_LOAD_DONE);
Amol Jadib6be5c12012-11-14 13:39:51 -08001001
Shashank Mittalcd98d472011-08-02 14:29:24 -07001002 offset = imagesize_actual;
Deepa Dinamanid14bb4d2013-07-12 17:28:29 -07001003
1004 if (check_aboot_addr_range_overlap(image_addr + offset, page_size))
1005 {
1006 dprintf(CRITICAL, "Signature read buffer address overlaps with aboot addresses.\n");
1007 return -1;
1008 }
1009
Shashank Mittalcd98d472011-08-02 14:29:24 -07001010 /* Read signature */
1011 if(mmc_read(ptn + offset, (void *)(image_addr + offset), page_size))
1012 {
1013 dprintf(CRITICAL, "ERROR: Cannot read boot image signature\n");
Deepa Dinamani0e163a42013-05-24 17:08:15 -07001014 return -1;
Shashank Mittalcd98d472011-08-02 14:29:24 -07001015 }
Amol Jadib6be5c12012-11-14 13:39:51 -08001016
Deepa Dinamani0e163a42013-05-24 17:08:15 -07001017 verify_signed_bootimg(image_addr, imagesize_actual);
Shashank Mittalcd98d472011-08-02 14:29:24 -07001018
Neeti Desai465491e2012-07-31 12:53:35 -07001019 /* Move kernel, ramdisk and device tree to correct address */
Shashank Mittalcd98d472011-08-02 14:29:24 -07001020 memmove((void*) hdr->kernel_addr, (char *)(image_addr + page_size), hdr->kernel_size);
1021 memmove((void*) hdr->ramdisk_addr, (char *)(image_addr + page_size + kernel_actual), hdr->ramdisk_size);
Shashank Mittal162244e2011-08-08 19:01:25 -07001022
Neeti Desai465491e2012-07-31 12:53:35 -07001023 #if DEVICE_TREE
1024 if(hdr->dt_size) {
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -07001025 dt_table_offset = ((uint32_t)image_addr + page_size + kernel_actual + ramdisk_actual + second_actual);
Deepa Dinamani19648b42013-09-05 17:05:55 -07001026 table = (struct dt_table*) dt_table_offset;
Neeti Desai465491e2012-07-31 12:53:35 -07001027
Deepa Dinamani19648b42013-09-05 17:05:55 -07001028 if (dev_tree_validate(table, hdr->page_size, &dt_hdr_size) != 0) {
Neeti Desai465491e2012-07-31 12:53:35 -07001029 dprintf(CRITICAL, "ERROR: Cannot validate Device Tree Table \n");
1030 return -1;
1031 }
Deepa Dinamani19648b42013-09-05 17:05:55 -07001032
Neeti Desai465491e2012-07-31 12:53:35 -07001033 /* Find index of device tree within device tree table */
Joel Kingaa335dc2013-06-03 16:11:08 -07001034 if(dev_tree_get_entry_info(table, &dt_entry) != 0){
Neeti Desai465491e2012-07-31 12:53:35 -07001035 dprintf(CRITICAL, "ERROR: Device Tree Blob cannot be found\n");
1036 return -1;
1037 }
1038
Deepa Dinamani0e163a42013-05-24 17:08:15 -07001039 /* Validate and Read device device tree in the "tags_add */
Joel Kingaa335dc2013-06-03 16:11:08 -07001040 if (check_aboot_addr_range_overlap(hdr->tags_addr, dt_entry.size))
Deepa Dinamani0e163a42013-05-24 17:08:15 -07001041 {
1042 dprintf(CRITICAL, "Device tree addresses overlap with aboot addresses.\n");
1043 return -1;
1044 }
1045
Joel Kingaa335dc2013-06-03 16:11:08 -07001046 memmove((void *)hdr->tags_addr, (char *)dt_table_offset + dt_entry.offset, dt_entry.size);
Channagoud Kadabi35095622013-03-01 13:53:05 -08001047 } else {
Dima Zavin77e41f32013-03-06 16:10:43 -08001048 /*
1049 * If appended dev tree is found, update the atags with
1050 * memory address to the DTB appended location on RAM.
1051 * Else update with the atags address in the kernel header
1052 */
1053 void *dtb;
1054 dtb = dev_tree_appended((void*) hdr->kernel_addr,
Dima Zavine63e5572013-05-03 12:23:06 -07001055 hdr->kernel_size,
1056 (void *)hdr->tags_addr);
Dima Zavin77e41f32013-03-06 16:10:43 -08001057 if (!dtb) {
1058 dprintf(CRITICAL, "ERROR: Appended Device Tree Blob not found\n");
1059 return -1;
1060 }
Neeti Desai465491e2012-07-31 12:53:35 -07001061 }
1062 #endif
Shashank Mittal23b8f422010-04-16 19:27:21 -07001063 }
Shashank Mittalcd98d472011-08-02 14:29:24 -07001064 else
1065 {
Amol Jadib6be5c12012-11-14 13:39:51 -08001066 second_actual = ROUND_TO_PAGE(hdr->second_size, page_mask);
Shashank Mittalcd98d472011-08-02 14:29:24 -07001067
Channagoud Kadabi82cf5c62014-08-24 22:17:34 -07001068 image_addr = (unsigned char *)target_get_scratch_address();
1069#if DEVICE_TREE
1070 dt_actual = ROUND_TO_PAGE(hdr->dt_size, page_mask);
1071 imagesize_actual = (page_size + kernel_actual + ramdisk_actual + dt_actual);
1072
1073 if (check_aboot_addr_range_overlap(hdr->tags_addr, dt_actual))
1074 {
1075 dprintf(CRITICAL, "Device tree addresses overlap with aboot addresses.\n");
1076 return -1;
1077 }
1078#else
1079 imagesize_actual = (page_size + kernel_actual + ramdisk_actual);
1080
1081#endif
1082 if (check_aboot_addr_range_overlap(image_addr, imagesize_actual))
1083 {
1084 dprintf(CRITICAL, "Boot image buffer address overlaps with aboot addresses.\n");
1085 return -1;
1086 }
1087
Amol Jadib6be5c12012-11-14 13:39:51 -08001088 dprintf(INFO, "Loading boot image (%d): start\n",
Channagoud Kadabi82cf5c62014-08-24 22:17:34 -07001089 imagesize_actual);
Amol Jadi492d5a52013-03-15 16:12:34 -07001090 bs_set_timestamp(BS_KERNEL_LOAD_START);
Amol Jadib6be5c12012-11-14 13:39:51 -08001091
Channagoud Kadabi82cf5c62014-08-24 22:17:34 -07001092 offset = 0;
Amol Jadib6be5c12012-11-14 13:39:51 -08001093
Channagoud Kadabi82cf5c62014-08-24 22:17:34 -07001094 /* Load the entire boot image */
1095 if (mmc_read(ptn + offset, (void *)image_addr, imagesize_actual)) {
1096 dprintf(CRITICAL, "ERROR: Cannot read boot image\n");
Shashank Mittalcd98d472011-08-02 14:29:24 -07001097 return -1;
1098 }
Amol Jadib6be5c12012-11-14 13:39:51 -08001099
1100 dprintf(INFO, "Loading boot image (%d): done\n",
Channagoud Kadabi82cf5c62014-08-24 22:17:34 -07001101 imagesize_actual);
Amol Jadi492d5a52013-03-15 16:12:34 -07001102 bs_set_timestamp(BS_KERNEL_LOAD_DONE);
Neeti Desai465491e2012-07-31 12:53:35 -07001103
Channagoud Kadabi82cf5c62014-08-24 22:17:34 -07001104 #ifdef TZ_SAVE_KERNEL_HASH
1105 aboot_save_boot_hash_mmc(image_addr, imagesize_actual);
1106 #endif /* TZ_SAVE_KERNEL_HASH */
1107
1108 /* Move kernel, ramdisk and device tree to correct address */
1109 memmove((void*) hdr->kernel_addr, (char *)(image_addr + page_size), hdr->kernel_size);
1110 memmove((void*) hdr->ramdisk_addr, (char *)(image_addr + page_size + kernel_actual), hdr->ramdisk_size);
Neeti Desai465491e2012-07-31 12:53:35 -07001111
1112 #if DEVICE_TREE
Channagoud Kadabi82cf5c62014-08-24 22:17:34 -07001113 if(hdr->dt_size) {
1114 dt_table_offset = ((uint32_t)image_addr + page_size + kernel_actual + ramdisk_actual + second_actual);
1115 table = (struct dt_table*) dt_table_offset;
Neeti Desai465491e2012-07-31 12:53:35 -07001116
Deepa Dinamani19648b42013-09-05 17:05:55 -07001117 if (dev_tree_validate(table, hdr->page_size, &dt_hdr_size) != 0) {
Neeti Desai465491e2012-07-31 12:53:35 -07001118 dprintf(CRITICAL, "ERROR: Cannot validate Device Tree Table \n");
1119 return -1;
1120 }
1121
Joel Kingaa335dc2013-06-03 16:11:08 -07001122 /* Find index of device tree within device tree table */
1123 if(dev_tree_get_entry_info(table, &dt_entry) != 0){
Neeti Desai465491e2012-07-31 12:53:35 -07001124 dprintf(CRITICAL, "ERROR: Getting device tree address failed\n");
1125 return -1;
1126 }
1127
Channagoud Kadabi82cf5c62014-08-24 22:17:34 -07001128 /* Validate and Read device device tree in the tags_addr */
Joel Kingaa335dc2013-06-03 16:11:08 -07001129 if (check_aboot_addr_range_overlap(hdr->tags_addr, dt_entry.size))
Deepa Dinamani0e163a42013-05-24 17:08:15 -07001130 {
1131 dprintf(CRITICAL, "Device tree addresses overlap with aboot addresses.\n");
1132 return -1;
1133 }
1134
Channagoud Kadabi82cf5c62014-08-24 22:17:34 -07001135 memmove((void *)hdr->tags_addr, (char *)dt_table_offset + dt_entry.offset, dt_entry.size);
Channagoud Kadabi35095622013-03-01 13:53:05 -08001136 } else {
Aparna Mallavarapu33127372014-06-03 22:15:54 +05301137 /* Validate the tags_addr */
1138 if (check_aboot_addr_range_overlap(hdr->tags_addr, kernel_actual))
1139 {
1140 dprintf(CRITICAL, "Device tree addresses overlap with aboot addresses.\n");
1141 return -1;
1142 }
Dima Zavin77e41f32013-03-06 16:10:43 -08001143 /*
1144 * If appended dev tree is found, update the atags with
1145 * memory address to the DTB appended location on RAM.
1146 * Else update with the atags address in the kernel header
1147 */
1148 void *dtb;
1149 dtb = dev_tree_appended((void*) hdr->kernel_addr,
Dima Zavine63e5572013-05-03 12:23:06 -07001150 kernel_actual,
1151 (void *)hdr->tags_addr);
Dima Zavin77e41f32013-03-06 16:10:43 -08001152 if (!dtb) {
1153 dprintf(CRITICAL, "ERROR: Appended Device Tree Blob not found\n");
1154 return -1;
1155 }
Neeti Desai465491e2012-07-31 12:53:35 -07001156 }
1157 #endif
Shashank Mittalcd98d472011-08-02 14:29:24 -07001158 }
Shashank Mittal23b8f422010-04-16 19:27:21 -07001159
Stanimir Varbanov69ec5462013-07-18 18:17:42 +03001160 if (boot_into_recovery && !device.is_unlocked && !device.is_tampered)
1161 target_load_ssd_keystore();
1162
Shashank Mittal23b8f422010-04-16 19:27:21 -07001163unified_boot:
Shashank Mittal23b8f422010-04-16 19:27:21 -07001164
Dima Zavin77e41f32013-03-06 16:10:43 -08001165 boot_linux((void *)hdr->kernel_addr, (void *)hdr->tags_addr,
Dima Zavinbd3daa02013-03-26 11:06:44 -07001166 (const char *)hdr->cmdline, board_machtype(),
Shashank Mittal23b8f422010-04-16 19:27:21 -07001167 (void *)hdr->ramdisk_addr, hdr->ramdisk_size);
1168
1169 return 0;
1170}
1171
Dima Zavin214cc642009-01-26 11:16:21 -08001172int boot_linux_from_flash(void)
1173{
1174 struct boot_img_hdr *hdr = (void*) buf;
Dima Zavin214cc642009-01-26 11:16:21 -08001175 struct ptentry *ptn;
1176 struct ptable *ptable;
1177 unsigned offset = 0;
Chandan Uddarajude85d3f2010-01-05 16:32:33 -08001178
Shashank Mittalcd98d472011-08-02 14:29:24 -07001179 unsigned char *image_addr = 0;
1180 unsigned kernel_actual;
1181 unsigned ramdisk_actual;
1182 unsigned imagesize_actual;
Amol Jadib6be5c12012-11-14 13:39:51 -08001183 unsigned second_actual;
Shashank Mittalcd98d472011-08-02 14:29:24 -07001184
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -07001185#if DEVICE_TREE
1186 struct dt_table *table;
Joel Kingaa335dc2013-06-03 16:11:08 -07001187 struct dt_entry dt_entry;
Deepa Dinamani7aaf83d2012-12-21 11:27:01 -08001188 uint32_t dt_actual;
Deepa Dinamani19648b42013-09-05 17:05:55 -07001189 uint32_t dt_hdr_size;
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -07001190#endif
1191
David Ng183a7422009-12-07 14:55:21 -08001192 if (target_is_emmc_boot()) {
1193 hdr = (struct boot_img_hdr *)EMMC_BOOT_IMG_HEADER_ADDR;
1194 if (memcmp(hdr->magic, BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
1195 dprintf(CRITICAL, "ERROR: Invalid boot image header\n");
1196 return -1;
1197 }
1198 goto continue_boot;
1199 }
1200
Dima Zavin214cc642009-01-26 11:16:21 -08001201 ptable = flash_get_ptable();
1202 if (ptable == NULL) {
1203 dprintf(CRITICAL, "ERROR: Partition table not found\n");
1204 return -1;
1205 }
1206
Chandan Uddarajude85d3f2010-01-05 16:32:33 -08001207 if(!boot_into_recovery)
1208 {
1209 ptn = ptable_find(ptable, "boot");
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -07001210
Chandan Uddarajude85d3f2010-01-05 16:32:33 -08001211 if (ptn == NULL) {
1212 dprintf(CRITICAL, "ERROR: No boot partition found\n");
1213 return -1;
1214 }
1215 }
1216 else
1217 {
1218 ptn = ptable_find(ptable, "recovery");
1219 if (ptn == NULL) {
1220 dprintf(CRITICAL, "ERROR: No recovery partition found\n");
1221 return -1;
1222 }
Dima Zavin214cc642009-01-26 11:16:21 -08001223 }
1224
Shashank Mittaldcc2e352009-11-19 19:11:16 -08001225 if (flash_read(ptn, offset, buf, page_size)) {
Dima Zavin214cc642009-01-26 11:16:21 -08001226 dprintf(CRITICAL, "ERROR: Cannot read boot image header\n");
1227 return -1;
1228 }
Dima Zavin214cc642009-01-26 11:16:21 -08001229
1230 if (memcmp(hdr->magic, BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
Kinson Chik kchik@codeaurora.org82e4ae62011-04-12 17:42:07 -07001231 dprintf(CRITICAL, "ERROR: Invalid boot image header\n");
Dima Zavin214cc642009-01-26 11:16:21 -08001232 return -1;
1233 }
1234
Shashank Mittaldcc2e352009-11-19 19:11:16 -08001235 if (hdr->page_size != page_size) {
Kinson Chik kchik@codeaurora.org82e4ae62011-04-12 17:42:07 -07001236 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 -08001237 return -1;
1238 }
1239
Channagoud Kadabia22144f2013-03-20 11:49:01 -07001240 /*
1241 * Update the kernel/ramdisk/tags address if the boot image header
1242 * has default values, these default values come from mkbootimg when
1243 * the boot image is flashed using fastboot flash:raw
1244 */
Abhimanyu Kapur0f79d572014-02-19 22:03:02 -08001245 update_ker_tags_rdisk_addr(hdr, false);
Channagoud Kadabia22144f2013-03-20 11:49:01 -07001246
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001247 /* Get virtual addresses since the hdr saves physical addresses. */
Deepa Dinamani0e163a42013-05-24 17:08:15 -07001248 hdr->kernel_addr = VA((addr_t)(hdr->kernel_addr));
1249 hdr->ramdisk_addr = VA((addr_t)(hdr->ramdisk_addr));
1250 hdr->tags_addr = VA((addr_t)(hdr->tags_addr));
1251
1252 kernel_actual = ROUND_TO_PAGE(hdr->kernel_size, page_mask);
1253 ramdisk_actual = ROUND_TO_PAGE(hdr->ramdisk_size, page_mask);
1254
1255 /* Check if the addresses in the header are valid. */
1256 if (check_aboot_addr_range_overlap(hdr->kernel_addr, kernel_actual) ||
1257 check_aboot_addr_range_overlap(hdr->ramdisk_addr, ramdisk_actual))
1258 {
1259 dprintf(CRITICAL, "kernel/ramdisk addresses overlap with aboot addresses.\n");
1260 return -1;
1261 }
1262
1263#ifndef DEVICE_TREE
1264 if (check_aboot_addr_range_overlap(hdr->tags_addr, MAX_TAGS_SIZE))
1265 {
1266 dprintf(CRITICAL, "Tags addresses overlap with aboot addresses.\n");
1267 return -1;
1268 }
1269#endif
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001270
Shashank Mittalcd98d472011-08-02 14:29:24 -07001271 /* Authenticate Kernel */
Deepa Dinamani23b60d42013-06-24 18:10:52 -07001272 if(target_use_signed_kernel() && (!device.is_unlocked))
Shashank Mittalcd98d472011-08-02 14:29:24 -07001273 {
1274 image_addr = (unsigned char *)target_get_scratch_address();
Deepa Dinamani0e163a42013-05-24 17:08:15 -07001275 offset = 0;
1276
Deepa Dinamani7aaf83d2012-12-21 11:27:01 -08001277#if DEVICE_TREE
1278 dt_actual = ROUND_TO_PAGE(hdr->dt_size, page_mask);
1279 imagesize_actual = (page_size + kernel_actual + ramdisk_actual + dt_actual);
Deepa Dinamani0e163a42013-05-24 17:08:15 -07001280
1281 if (check_aboot_addr_range_overlap(hdr->tags_addr, hdr->dt_size))
1282 {
1283 dprintf(CRITICAL, "Device tree addresses overlap with aboot addresses.\n");
1284 return -1;
1285 }
Deepa Dinamani7aaf83d2012-12-21 11:27:01 -08001286#else
Shashank Mittalcd98d472011-08-02 14:29:24 -07001287 imagesize_actual = (page_size + kernel_actual + ramdisk_actual);
Deepa Dinamani7aaf83d2012-12-21 11:27:01 -08001288#endif
Shashank Mittal162244e2011-08-08 19:01:25 -07001289
Amol Jadib6be5c12012-11-14 13:39:51 -08001290 dprintf(INFO, "Loading boot image (%d): start\n", imagesize_actual);
Amol Jadi492d5a52013-03-15 16:12:34 -07001291 bs_set_timestamp(BS_KERNEL_LOAD_START);
Amol Jadib6be5c12012-11-14 13:39:51 -08001292
Shashank Mittalcd98d472011-08-02 14:29:24 -07001293 /* Read image without signature */
1294 if (flash_read(ptn, offset, (void *)image_addr, imagesize_actual))
1295 {
1296 dprintf(CRITICAL, "ERROR: Cannot read boot image\n");
1297 return -1;
1298 }
Dima Zavin214cc642009-01-26 11:16:21 -08001299
Amol Jadib6be5c12012-11-14 13:39:51 -08001300 dprintf(INFO, "Loading boot image (%d): done\n", imagesize_actual);
Amol Jadi492d5a52013-03-15 16:12:34 -07001301 bs_set_timestamp(BS_KERNEL_LOAD_DONE);
Amol Jadib6be5c12012-11-14 13:39:51 -08001302
Shashank Mittalcd98d472011-08-02 14:29:24 -07001303 offset = imagesize_actual;
1304 /* Read signature */
1305 if (flash_read(ptn, offset, (void *)(image_addr + offset), page_size))
1306 {
1307 dprintf(CRITICAL, "ERROR: Cannot read boot image signature\n");
Deepa Dinamani0e163a42013-05-24 17:08:15 -07001308 return -1;
Shashank Mittalcd98d472011-08-02 14:29:24 -07001309 }
Shashank Mittalcd98d472011-08-02 14:29:24 -07001310
Deepa Dinamani0e163a42013-05-24 17:08:15 -07001311 verify_signed_bootimg(image_addr, imagesize_actual);
Shashank Mittalcd98d472011-08-02 14:29:24 -07001312
1313 /* Move kernel and ramdisk to correct address */
1314 memmove((void*) hdr->kernel_addr, (char *)(image_addr + page_size), hdr->kernel_size);
1315 memmove((void*) hdr->ramdisk_addr, (char *)(image_addr + page_size + kernel_actual), hdr->ramdisk_size);
Deepa Dinamani7aaf83d2012-12-21 11:27:01 -08001316#if DEVICE_TREE
Deepa Dinamani0e163a42013-05-24 17:08:15 -07001317 /* Validate and Read device device tree in the "tags_add */
Joel Kingaa335dc2013-06-03 16:11:08 -07001318 if (check_aboot_addr_range_overlap(hdr->tags_addr, dt_entry.size))
Deepa Dinamani0e163a42013-05-24 17:08:15 -07001319 {
1320 dprintf(CRITICAL, "Device tree addresses overlap with aboot addresses.\n");
1321 return -1;
1322 }
1323
Deepa Dinamani7aaf83d2012-12-21 11:27:01 -08001324 memmove((void*) hdr->tags_addr, (char *)(image_addr + page_size + kernel_actual + ramdisk_actual), hdr->dt_size);
1325#endif
Shashank Mittal162244e2011-08-08 19:01:25 -07001326
1327 /* Make sure everything from scratch address is read before next step!*/
Shashank Mittala0032282011-08-26 14:50:11 -07001328 if(device.is_tampered)
Shashank Mittal162244e2011-08-08 19:01:25 -07001329 {
1330 write_device_info_flash(&device);
1331 }
Channagoud Kadabi5c86fe32012-02-16 10:58:48 +05301332#if USE_PCOM_SECBOOT
1333 set_tamper_flag(device.is_tampered);
1334#endif
Shashank Mittalcd98d472011-08-02 14:29:24 -07001335 }
1336 else
1337 {
Shashank Mittal162244e2011-08-08 19:01:25 -07001338 offset = page_size;
1339
Amol Jadib6be5c12012-11-14 13:39:51 -08001340 kernel_actual = ROUND_TO_PAGE(hdr->kernel_size, page_mask);
1341 ramdisk_actual = ROUND_TO_PAGE(hdr->ramdisk_size, page_mask);
1342 second_actual = ROUND_TO_PAGE(hdr->second_size, page_mask);
1343
1344 dprintf(INFO, "Loading boot image (%d): start\n",
1345 kernel_actual + ramdisk_actual);
Amol Jadi492d5a52013-03-15 16:12:34 -07001346 bs_set_timestamp(BS_KERNEL_LOAD_START);
Amol Jadib6be5c12012-11-14 13:39:51 -08001347
1348 if (flash_read(ptn, offset, (void *)hdr->kernel_addr, kernel_actual)) {
Shashank Mittalcd98d472011-08-02 14:29:24 -07001349 dprintf(CRITICAL, "ERROR: Cannot read kernel image\n");
1350 return -1;
1351 }
Amol Jadib6be5c12012-11-14 13:39:51 -08001352 offset += kernel_actual;
Shashank Mittalcd98d472011-08-02 14:29:24 -07001353
Amol Jadib6be5c12012-11-14 13:39:51 -08001354 if (flash_read(ptn, offset, (void *)hdr->ramdisk_addr, ramdisk_actual)) {
Shashank Mittalcd98d472011-08-02 14:29:24 -07001355 dprintf(CRITICAL, "ERROR: Cannot read ramdisk image\n");
1356 return -1;
1357 }
Amol Jadib6be5c12012-11-14 13:39:51 -08001358 offset += ramdisk_actual;
1359
1360 dprintf(INFO, "Loading boot image (%d): done\n",
1361 kernel_actual + ramdisk_actual);
Amol Jadi492d5a52013-03-15 16:12:34 -07001362 bs_set_timestamp(BS_KERNEL_LOAD_DONE);
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -07001363
1364 if(hdr->second_size != 0) {
Amol Jadib6be5c12012-11-14 13:39:51 -08001365 offset += second_actual;
1366 /* Second image loading not implemented. */
1367 ASSERT(0);
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -07001368 }
1369
1370#if DEVICE_TREE
1371 if(hdr->dt_size != 0) {
1372
1373 /* Read the device tree table into buffer */
1374 if(flash_read(ptn, offset, (void *) dt_buf, page_size)) {
1375 dprintf(CRITICAL, "ERROR: Cannot read the Device Tree Table\n");
1376 return -1;
1377 }
1378
1379 table = (struct dt_table*) dt_buf;
1380
Deepa Dinamani19648b42013-09-05 17:05:55 -07001381 if (dev_tree_validate(table, hdr->page_size, &dt_hdr_size) != 0) {
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -07001382 dprintf(CRITICAL, "ERROR: Cannot validate Device Tree Table \n");
1383 return -1;
1384 }
1385
Deepa Dinamani19648b42013-09-05 17:05:55 -07001386 table = (struct dt_table*) memalign(CACHE_LINE, dt_hdr_size);
1387 if (!table)
1388 return -1;
1389
1390 /* Read the entire device tree table into buffer */
1391 if(flash_read(ptn, offset, (void *)table, dt_hdr_size)) {
1392 dprintf(CRITICAL, "ERROR: Cannot read the Device Tree Table\n");
1393 return -1;
1394 }
1395
1396
Joel Kingaa335dc2013-06-03 16:11:08 -07001397 /* Find index of device tree within device tree table */
1398 if(dev_tree_get_entry_info(table, &dt_entry) != 0){
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -07001399 dprintf(CRITICAL, "ERROR: Getting device tree address failed\n");
1400 return -1;
1401 }
1402
Deepa Dinamani0e163a42013-05-24 17:08:15 -07001403 /* Validate and Read device device tree in the "tags_add */
Joel Kingaa335dc2013-06-03 16:11:08 -07001404 if (check_aboot_addr_range_overlap(hdr->tags_addr, dt_entry.size))
Deepa Dinamani0e163a42013-05-24 17:08:15 -07001405 {
1406 dprintf(CRITICAL, "Device tree addresses overlap with aboot addresses.\n");
1407 return -1;
1408 }
1409
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -07001410 /* Read device device tree in the "tags_add */
Joel Kingaa335dc2013-06-03 16:11:08 -07001411 if(flash_read(ptn, offset + dt_entry.offset,
1412 (void *)hdr->tags_addr, dt_entry.size)) {
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -07001413 dprintf(CRITICAL, "ERROR: Cannot read device tree\n");
1414 return -1;
1415 }
1416 }
1417#endif
1418
Shashank Mittalcd98d472011-08-02 14:29:24 -07001419 }
David Ng183a7422009-12-07 14:55:21 -08001420continue_boot:
Dima Zavin214cc642009-01-26 11:16:21 -08001421
Dima Zavin214cc642009-01-26 11:16:21 -08001422 /* TODO: create/pass atags to kernel */
1423
Ajay Dudanie28a6072011-07-01 13:59:46 -07001424 boot_linux((void *)hdr->kernel_addr, (void *)hdr->tags_addr,
Dima Zavinbd3daa02013-03-26 11:06:44 -07001425 (const char *)hdr->cmdline, board_machtype(),
Dima Zavin214cc642009-01-26 11:16:21 -08001426 (void *)hdr->ramdisk_addr, hdr->ramdisk_size);
1427
1428 return 0;
1429}
Brian Swetland9c4c0752009-01-25 16:23:50 -08001430
Abhimanyu Kapur0f79d572014-02-19 22:03:02 -08001431BUF_DMA_ALIGN(info_buf, BOOT_IMG_MAX_PAGE_SIZE);
Shashank Mittal162244e2011-08-08 19:01:25 -07001432void write_device_info_mmc(device_info *dev)
1433{
1434 struct device_info *info = (void*) info_buf;
1435 unsigned long long ptn = 0;
1436 unsigned long long size;
1437 int index = INVALID_PTN;
Channagoud Kadabi749b0f82013-09-10 22:36:02 -07001438 uint32_t blocksize;
Sundarajan Srinivasand3514bb2013-12-04 17:02:00 -08001439 uint8_t lun = 0;
Shashank Mittal162244e2011-08-08 19:01:25 -07001440
Channagoud Kadabi5d0371c2014-10-21 22:27:07 -07001441#if VERIFIED_BOOT
1442 index = partition_get_index("devinfo");
1443#else
Shashank Mittal162244e2011-08-08 19:01:25 -07001444 index = partition_get_index("aboot");
Channagoud Kadabi5d0371c2014-10-21 22:27:07 -07001445#endif
1446
Shashank Mittal162244e2011-08-08 19:01:25 -07001447 ptn = partition_get_offset(index);
1448 if(ptn == 0)
1449 {
1450 return;
1451 }
1452
Sundarajan Srinivasand3514bb2013-12-04 17:02:00 -08001453 lun = partition_get_lun(index);
1454 mmc_set_lun(lun);
1455
Shashank Mittal162244e2011-08-08 19:01:25 -07001456 size = partition_get_size(index);
1457
1458 memcpy(info, dev, sizeof(device_info));
1459
Channagoud Kadabi749b0f82013-09-10 22:36:02 -07001460 blocksize = mmc_get_device_blocksize();
1461
Channagoud Kadabi5d0371c2014-10-21 22:27:07 -07001462#if VERIFIED_BOOT
1463 if(mmc_write(ptn, blocksize, (void *)info_buf))
1464#else
Channagoud Kadabi749b0f82013-09-10 22:36:02 -07001465 if(mmc_write((ptn + size - blocksize), blocksize, (void *)info_buf))
Channagoud Kadabi5d0371c2014-10-21 22:27:07 -07001466#endif
Shashank Mittal162244e2011-08-08 19:01:25 -07001467 {
1468 dprintf(CRITICAL, "ERROR: Cannot write device info\n");
1469 return;
1470 }
1471}
1472
1473void read_device_info_mmc(device_info *dev)
1474{
1475 struct device_info *info = (void*) info_buf;
1476 unsigned long long ptn = 0;
1477 unsigned long long size;
1478 int index = INVALID_PTN;
Channagoud Kadabi749b0f82013-09-10 22:36:02 -07001479 uint32_t blocksize;
Shashank Mittal162244e2011-08-08 19:01:25 -07001480
Channagoud Kadabi5d0371c2014-10-21 22:27:07 -07001481#if VERIFIED_BOOT
1482 index = partition_get_index("devinfo");
1483#else
Shashank Mittal162244e2011-08-08 19:01:25 -07001484 index = partition_get_index("aboot");
Channagoud Kadabi5d0371c2014-10-21 22:27:07 -07001485#endif
1486
Shashank Mittal162244e2011-08-08 19:01:25 -07001487 ptn = partition_get_offset(index);
1488 if(ptn == 0)
1489 {
1490 return;
1491 }
1492
Channagoud Kadabi5d0371c2014-10-21 22:27:07 -07001493 mmc_set_lun(partition_get_lun(index));
1494
Shashank Mittal162244e2011-08-08 19:01:25 -07001495 size = partition_get_size(index);
1496
Channagoud Kadabi749b0f82013-09-10 22:36:02 -07001497 blocksize = mmc_get_device_blocksize();
1498
Channagoud Kadabi5d0371c2014-10-21 22:27:07 -07001499#if VERIFIED_BOOT
1500 if(mmc_read(ptn, (void *)info_buf, blocksize))
1501#else
Channagoud Kadabi749b0f82013-09-10 22:36:02 -07001502 if(mmc_read((ptn + size - blocksize), (void *)info_buf, blocksize))
Channagoud Kadabi5d0371c2014-10-21 22:27:07 -07001503#endif
Shashank Mittal162244e2011-08-08 19:01:25 -07001504 {
1505 dprintf(CRITICAL, "ERROR: Cannot read device info\n");
1506 return;
1507 }
1508
1509 if (memcmp(info->magic, DEVICE_MAGIC, DEVICE_MAGIC_SIZE))
1510 {
1511 memcpy(info->magic, DEVICE_MAGIC, DEVICE_MAGIC_SIZE);
Shashank Mittal7e033062014-09-25 19:58:07 -07001512#if DEFAULT_UNLOCK
1513 info->is_unlocked = 1;
1514#else
Shashank Mittal162244e2011-08-08 19:01:25 -07001515 info->is_unlocked = 0;
Shashank Mittal7e033062014-09-25 19:58:07 -07001516#endif
1517 info->is_verified = 0;
Shashank Mittala0032282011-08-26 14:50:11 -07001518 info->is_tampered = 0;
Ameya Thakur11cf1a62013-08-05 12:44:48 -07001519 info->charger_screen_enabled = 0;
Shashank Mittal162244e2011-08-08 19:01:25 -07001520
1521 write_device_info_mmc(info);
1522 }
1523 memcpy(dev, info, sizeof(device_info));
1524}
1525
1526void write_device_info_flash(device_info *dev)
1527{
1528 struct device_info *info = (void *) info_buf;
1529 struct ptentry *ptn;
1530 struct ptable *ptable;
1531
1532 ptable = flash_get_ptable();
1533 if (ptable == NULL)
1534 {
1535 dprintf(CRITICAL, "ERROR: Partition table not found\n");
1536 return;
1537 }
1538
1539 ptn = ptable_find(ptable, "devinfo");
1540 if (ptn == NULL)
1541 {
1542 dprintf(CRITICAL, "ERROR: No boot partition found\n");
1543 return;
1544 }
1545
1546 memcpy(info, dev, sizeof(device_info));
1547
1548 if (flash_write(ptn, 0, (void *)info_buf, page_size))
1549 {
1550 dprintf(CRITICAL, "ERROR: Cannot write device info\n");
1551 return;
1552 }
1553}
1554
1555void read_device_info_flash(device_info *dev)
1556{
1557 struct device_info *info = (void*) info_buf;
1558 struct ptentry *ptn;
1559 struct ptable *ptable;
1560
1561 ptable = flash_get_ptable();
1562 if (ptable == NULL)
1563 {
1564 dprintf(CRITICAL, "ERROR: Partition table not found\n");
1565 return;
1566 }
1567
1568 ptn = ptable_find(ptable, "devinfo");
1569 if (ptn == NULL)
1570 {
1571 dprintf(CRITICAL, "ERROR: No boot partition found\n");
1572 return;
1573 }
1574
1575 if (flash_read(ptn, 0, (void *)info_buf, page_size))
1576 {
1577 dprintf(CRITICAL, "ERROR: Cannot write device info\n");
1578 return;
1579 }
1580
1581 if (memcmp(info->magic, DEVICE_MAGIC, DEVICE_MAGIC_SIZE))
1582 {
Shashank Mittal162244e2011-08-08 19:01:25 -07001583 memcpy(info->magic, DEVICE_MAGIC, DEVICE_MAGIC_SIZE);
1584 info->is_unlocked = 0;
Shashank Mittala0032282011-08-26 14:50:11 -07001585 info->is_tampered = 0;
Shashank Mittal162244e2011-08-08 19:01:25 -07001586 write_device_info_flash(info);
1587 }
1588 memcpy(dev, info, sizeof(device_info));
1589}
1590
1591void write_device_info(device_info *dev)
1592{
1593 if(target_is_emmc_boot())
1594 {
1595 write_device_info_mmc(dev);
1596 }
1597 else
1598 {
1599 write_device_info_flash(dev);
1600 }
1601}
1602
1603void read_device_info(device_info *dev)
1604{
1605 if(target_is_emmc_boot())
1606 {
1607 read_device_info_mmc(dev);
1608 }
1609 else
1610 {
1611 read_device_info_flash(dev);
1612 }
1613}
1614
1615void reset_device_info()
1616{
1617 dprintf(ALWAYS, "reset_device_info called.");
Shashank Mittala0032282011-08-26 14:50:11 -07001618 device.is_tampered = 0;
Shashank Mittal162244e2011-08-08 19:01:25 -07001619 write_device_info(&device);
1620}
1621
1622void set_device_root()
1623{
1624 dprintf(ALWAYS, "set_device_root called.");
Shashank Mittala0032282011-08-26 14:50:11 -07001625 device.is_tampered = 1;
Shashank Mittal162244e2011-08-08 19:01:25 -07001626 write_device_info(&device);
1627}
1628
Amol Jadicb524072012-08-09 16:40:18 -07001629#if DEVICE_TREE
1630int copy_dtb(uint8_t *boot_image_start)
1631{
1632 uint32 dt_image_offset = 0;
1633 uint32_t n;
1634 struct dt_table *table;
Joel Kingaa335dc2013-06-03 16:11:08 -07001635 struct dt_entry dt_entry;
Deepa Dinamani19648b42013-09-05 17:05:55 -07001636 uint32_t dt_hdr_size;
Amol Jadicb524072012-08-09 16:40:18 -07001637
1638 struct boot_img_hdr *hdr = (struct boot_img_hdr *) (boot_image_start);
1639
Amol Jadicb524072012-08-09 16:40:18 -07001640 if(hdr->dt_size != 0) {
1641
1642 /* add kernel offset */
1643 dt_image_offset += page_size;
1644 n = ROUND_TO_PAGE(hdr->kernel_size, page_mask);
1645 dt_image_offset += n;
1646
1647 /* add ramdisk offset */
1648 n = ROUND_TO_PAGE(hdr->ramdisk_size, page_mask);
1649 dt_image_offset += n;
1650
1651 /* add second offset */
1652 if(hdr->second_size != 0) {
1653 n = ROUND_TO_PAGE(hdr->second_size, page_mask);
1654 dt_image_offset += n;
1655 }
1656
1657 /* offset now point to start of dt.img */
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -07001658 table = (struct dt_table*)(boot_image_start + dt_image_offset);
Amol Jadicb524072012-08-09 16:40:18 -07001659
Deepa Dinamani19648b42013-09-05 17:05:55 -07001660 if (dev_tree_validate(table, hdr->page_size, &dt_hdr_size) != 0) {
Amol Jadicb524072012-08-09 16:40:18 -07001661 dprintf(CRITICAL, "ERROR: Cannot validate Device Tree Table \n");
1662 return -1;
1663 }
Joel Kingaa335dc2013-06-03 16:11:08 -07001664 /* Find index of device tree within device tree table */
1665 if(dev_tree_get_entry_info(table, &dt_entry) != 0){
Amol Jadicb524072012-08-09 16:40:18 -07001666 dprintf(CRITICAL, "ERROR: Getting device tree address failed\n");
1667 return -1;
1668 }
1669
Deepa Dinamani0e163a42013-05-24 17:08:15 -07001670 /* Validate and Read device device tree in the "tags_add */
Joel Kingaa335dc2013-06-03 16:11:08 -07001671 if (check_aboot_addr_range_overlap(hdr->tags_addr, dt_entry.size))
Deepa Dinamani0e163a42013-05-24 17:08:15 -07001672 {
1673 dprintf(CRITICAL, "Device tree addresses overlap with aboot addresses.\n");
1674 return -1;
1675 }
1676
Amol Jadicb524072012-08-09 16:40:18 -07001677 /* Read device device tree in the "tags_add */
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001678 memmove((void*) hdr->tags_addr,
Joel Kingaa335dc2013-06-03 16:11:08 -07001679 boot_image_start + dt_image_offset + dt_entry.offset,
1680 dt_entry.size);
Channagoud Kadabi8e9020f2013-04-16 11:24:32 -07001681 } else
1682 return -1;
Amol Jadicb524072012-08-09 16:40:18 -07001683
1684 /* Everything looks fine. Return success. */
1685 return 0;
1686}
1687#endif
1688
Brian Swetland9c4c0752009-01-25 16:23:50 -08001689void cmd_boot(const char *arg, void *data, unsigned sz)
1690{
1691 unsigned kernel_actual;
1692 unsigned ramdisk_actual;
Channagoud Kadabifc3b31f2014-06-18 17:41:01 -07001693 uint32_t image_actual;
1694 uint32_t dt_actual = 0;
Channagoud Kadabi3d839012014-06-26 14:26:39 -07001695 uint32_t sig_actual = SIGNATURE_SIZE;
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001696 struct boot_img_hdr *hdr;
Abhimanyu Kapur0f79d572014-02-19 22:03:02 -08001697 struct kernel64_hdr *kptr;
Brian Swetland9c4c0752009-01-25 16:23:50 -08001698 char *ptr = ((char*) data);
Channagoud Kadabi8e9020f2013-04-16 11:24:32 -07001699 int ret = 0;
1700 uint8_t dtb_copied = 0;
Brian Swetland9c4c0752009-01-25 16:23:50 -08001701
Shashank Mittald3e54dd2014-08-28 15:24:02 -07001702#if VERIFIED_BOOT
1703 if(!device.is_unlocked)
1704 {
1705 fastboot_fail("unlock device to use this command");
1706 return;
1707 }
1708#endif
1709
Brian Swetland9c4c0752009-01-25 16:23:50 -08001710 if (sz < sizeof(hdr)) {
1711 fastboot_fail("invalid bootimage header");
1712 return;
1713 }
1714
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001715 hdr = (struct boot_img_hdr *)data;
Brian Swetland9c4c0752009-01-25 16:23:50 -08001716
1717 /* ensure commandline is terminated */
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001718 hdr->cmdline[BOOT_ARGS_SIZE-1] = 0;
Brian Swetland9c4c0752009-01-25 16:23:50 -08001719
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001720 if(target_is_emmc_boot() && hdr->page_size) {
1721 page_size = hdr->page_size;
Subbaraman Narayanamurthyfbe13a02010-09-10 11:51:12 -07001722 page_mask = page_size - 1;
1723 }
1724
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001725 kernel_actual = ROUND_TO_PAGE(hdr->kernel_size, page_mask);
1726 ramdisk_actual = ROUND_TO_PAGE(hdr->ramdisk_size, page_mask);
Channagoud Kadabifc3b31f2014-06-18 17:41:01 -07001727#if DEVICE_TREE
1728 dt_actual = ROUND_TO_PAGE(hdr->dt_size, page_mask);
1729#endif
1730
1731 image_actual = ADD_OF(page_size, kernel_actual);
1732 image_actual = ADD_OF(image_actual, ramdisk_actual);
1733 image_actual = ADD_OF(image_actual, dt_actual);
1734
Channagoud Kadabi3d839012014-06-26 14:26:39 -07001735 if (target_use_signed_kernel() && (!device.is_unlocked))
1736 image_actual = ADD_OF(image_actual, sig_actual);
1737
Channagoud Kadabifc3b31f2014-06-18 17:41:01 -07001738 /* sz should have atleast raw boot image */
1739 if (image_actual > sz) {
Channagoud Kadabi3d839012014-06-26 14:26:39 -07001740 fastboot_fail("bootimage: incomplete or not signed");
Channagoud Kadabifc3b31f2014-06-18 17:41:01 -07001741 return;
1742 }
1743
1744 /* Verify the boot image
1745 * device & page_size are initialized in aboot_init
1746 */
1747 if (target_use_signed_kernel() && (!device.is_unlocked))
Channagoud Kadabi3d839012014-06-26 14:26:39 -07001748 /* Pass size excluding signature size, otherwise we would try to
1749 * access signature beyond its length
1750 */
1751 verify_signed_bootimg((uint32_t)data, (image_actual - sig_actual));
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001752
Channagoud Kadabia22144f2013-03-20 11:49:01 -07001753 /*
1754 * Update the kernel/ramdisk/tags address if the boot image header
1755 * has default values, these default values come from mkbootimg when
1756 * the boot image is flashed using fastboot flash:raw
1757 */
Abhimanyu Kapur0f79d572014-02-19 22:03:02 -08001758 kptr = (struct kernel64_hdr*)((char*) data + page_size);
1759 update_ker_tags_rdisk_addr(hdr, IS_ARM64(kptr));
Dima Zavin3cadfff2013-03-21 14:30:48 -07001760
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001761 /* Get virtual addresses since the hdr saves physical addresses. */
1762 hdr->kernel_addr = VA(hdr->kernel_addr);
1763 hdr->ramdisk_addr = VA(hdr->ramdisk_addr);
1764 hdr->tags_addr = VA(hdr->tags_addr);
Brian Swetland9c4c0752009-01-25 16:23:50 -08001765
Deepa Dinamani0e163a42013-05-24 17:08:15 -07001766 /* Check if the addresses in the header are valid. */
1767 if (check_aboot_addr_range_overlap(hdr->kernel_addr, kernel_actual) ||
1768 check_aboot_addr_range_overlap(hdr->ramdisk_addr, ramdisk_actual))
1769 {
1770 dprintf(CRITICAL, "kernel/ramdisk addresses overlap with aboot addresses.\n");
Channagoud Kadabi881856c2013-12-03 11:19:20 -08001771 return;
Deepa Dinamani0e163a42013-05-24 17:08:15 -07001772 }
1773
Amol Jadicb524072012-08-09 16:40:18 -07001774#if DEVICE_TREE
1775 /* find correct dtb and copy it to right location */
Channagoud Kadabi8e9020f2013-04-16 11:24:32 -07001776 ret = copy_dtb(data);
1777
1778 dtb_copied = !ret ? 1 : 0;
Deepa Dinamani0e163a42013-05-24 17:08:15 -07001779#else
1780 if (check_aboot_addr_range_overlap(hdr->tags_addr, MAX_TAGS_SIZE))
1781 {
1782 dprintf(CRITICAL, "Tags addresses overlap with aboot addresses.\n");
Channagoud Kadabi881856c2013-12-03 11:19:20 -08001783 return;
Deepa Dinamani0e163a42013-05-24 17:08:15 -07001784 }
Channagoud Kadabi8e9020f2013-04-16 11:24:32 -07001785#endif
1786
1787 /* Load ramdisk & kernel */
1788 memmove((void*) hdr->ramdisk_addr, ptr + page_size + kernel_actual, hdr->ramdisk_size);
1789 memmove((void*) hdr->kernel_addr, ptr + page_size, hdr->kernel_size);
1790
1791#if DEVICE_TREE
1792 /*
1793 * If dtb is not found look for appended DTB in the kernel.
1794 * If appended dev tree is found, update the atags with
1795 * memory address to the DTB appended location on RAM.
1796 * Else update with the atags address in the kernel header
1797 */
1798 if (!dtb_copied) {
1799 void *dtb;
Dima Zavine63e5572013-05-03 12:23:06 -07001800 dtb = dev_tree_appended((void *)hdr->kernel_addr, hdr->kernel_size,
1801 (void *)hdr->tags_addr);
Channagoud Kadabi8e9020f2013-04-16 11:24:32 -07001802 if (!dtb) {
1803 fastboot_fail("dtb not found");
1804 return;
1805 }
Amol Jadicb524072012-08-09 16:40:18 -07001806 }
1807#endif
Brian Swetland9c4c0752009-01-25 16:23:50 -08001808
Deepa Dinamani0e163a42013-05-24 17:08:15 -07001809#ifndef DEVICE_TREE
1810 if (check_aboot_addr_range_overlap(hdr->tags_addr, MAX_TAGS_SIZE))
1811 {
1812 dprintf(CRITICAL, "Tags addresses overlap with aboot addresses.\n");
Channagoud Kadabi881856c2013-12-03 11:19:20 -08001813 return;
Deepa Dinamani0e163a42013-05-24 17:08:15 -07001814 }
1815#endif
1816
Brian Swetland9c4c0752009-01-25 16:23:50 -08001817 fastboot_okay("");
Amol Jadi7c4316c2013-10-07 14:19:26 -07001818 fastboot_stop();
Brian Swetland9c4c0752009-01-25 16:23:50 -08001819
Dima Zavin77e41f32013-03-06 16:10:43 -08001820 boot_linux((void*) hdr->kernel_addr, (void*) hdr->tags_addr,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001821 (const char*) hdr->cmdline, board_machtype(),
1822 (void*) hdr->ramdisk_addr, hdr->ramdisk_size);
Brian Swetland9c4c0752009-01-25 16:23:50 -08001823}
1824
Sridhar Parasurame94e8152014-10-24 14:06:03 -07001825void cmd_erase_nand(const char *arg, void *data, unsigned sz)
Dima Zavin214cc642009-01-26 11:16:21 -08001826{
1827 struct ptentry *ptn;
1828 struct ptable *ptable;
1829
1830 ptable = flash_get_ptable();
1831 if (ptable == NULL) {
1832 fastboot_fail("partition table doesn't exist");
1833 return;
1834 }
1835
1836 ptn = ptable_find(ptable, arg);
1837 if (ptn == NULL) {
1838 fastboot_fail("unknown partition name");
1839 return;
1840 }
1841
1842 if (flash_erase(ptn)) {
1843 fastboot_fail("failed to erase partition");
1844 return;
1845 }
1846 fastboot_okay("");
1847}
1848
Bikas Gurungd48bd242010-09-04 19:54:32 -07001849
1850void cmd_erase_mmc(const char *arg, void *data, unsigned sz)
1851{
Kun Liang2f1601a2013-08-12 16:29:54 +08001852 BUF_DMA_ALIGN(out, DEFAULT_ERASE_SIZE);
Bikas Gurungd48bd242010-09-04 19:54:32 -07001853 unsigned long long ptn = 0;
Oliver Wangcee448d2013-10-22 18:40:13 +08001854 unsigned long long size = 0;
Kinson Chikf1a43512011-07-14 11:28:39 -07001855 int index = INVALID_PTN;
Sundarajan Srinivasand3514bb2013-12-04 17:02:00 -08001856 uint8_t lun = 0;
Bikas Gurungd48bd242010-09-04 19:54:32 -07001857
Shashank Mittald3e54dd2014-08-28 15:24:02 -07001858#if VERIFIED_BOOT
1859 if(!strcmp(arg, KEYSTORE_PTN_NAME))
1860 {
1861 if(!device.is_unlocked)
1862 {
1863 fastboot_fail("unlock device to erase keystore");
1864 return;
1865 }
1866 }
1867#endif
1868
Kinson Chikf1a43512011-07-14 11:28:39 -07001869 index = partition_get_index(arg);
1870 ptn = partition_get_offset(index);
Oliver Wangcee448d2013-10-22 18:40:13 +08001871 size = partition_get_size(index);
Neeti Desaica8c9602011-10-06 11:40:00 -07001872
Kinson Chikf1a43512011-07-14 11:28:39 -07001873 if(ptn == 0) {
Neeti Desaica8c9602011-10-06 11:40:00 -07001874 fastboot_fail("Partition table doesn't exist\n");
Bikas Gurungd48bd242010-09-04 19:54:32 -07001875 return;
1876 }
Kun Liang2f1601a2013-08-12 16:29:54 +08001877
Sundarajan Srinivasand3514bb2013-12-04 17:02:00 -08001878 lun = partition_get_lun(index);
1879 mmc_set_lun(lun);
1880
Oliver Wangcee448d2013-10-22 18:40:13 +08001881#if MMC_SDHCI_SUPPORT
1882 if (mmc_erase_card(ptn, size)) {
1883 fastboot_fail("failed to erase partition\n");
1884 return;
1885 }
1886#else
Kun Liang2f1601a2013-08-12 16:29:54 +08001887 size = partition_get_size(index);
1888 if (size > DEFAULT_ERASE_SIZE)
1889 size = DEFAULT_ERASE_SIZE;
1890
neetidb4b24d62012-01-20 12:13:09 -08001891 /* Simple inefficient version of erase. Just writing
Kun Liang2f1601a2013-08-12 16:29:54 +08001892 0 in first several blocks */
1893 if (mmc_write(ptn , size, (unsigned int *)out)) {
neetidb4b24d62012-01-20 12:13:09 -08001894 fastboot_fail("failed to erase partition");
Bikas Gurungd48bd242010-09-04 19:54:32 -07001895 return;
1896 }
Oliver Wangcee448d2013-10-22 18:40:13 +08001897#endif
Bikas Gurungd48bd242010-09-04 19:54:32 -07001898 fastboot_okay("");
1899}
1900
Sridhar Parasurame94e8152014-10-24 14:06:03 -07001901void cmd_erase(const char *arg, void *data, unsigned sz)
1902{
1903 if(target_is_emmc_boot())
1904 cmd_erase_mmc(arg, data, sz);
1905 else
1906 cmd_erase_nand(arg, data, sz);
1907}
Bikas Gurungd48bd242010-09-04 19:54:32 -07001908
Ajay Dudani5c761132011-04-07 20:19:04 -07001909void cmd_flash_mmc_img(const char *arg, void *data, unsigned sz)
Shashank Mittal23b8f422010-04-16 19:27:21 -07001910{
1911 unsigned long long ptn = 0;
Subbaraman Narayanamurthyc95b5b12010-08-31 13:19:48 -07001912 unsigned long long size = 0;
Kinson Chikf1a43512011-07-14 11:28:39 -07001913 int index = INVALID_PTN;
Sundarajan Srinivasand3514bb2013-12-04 17:02:00 -08001914 char *token = NULL;
1915 char *pname = NULL;
1916 uint8_t lun = 0;
1917 bool lun_set = false;
Subbaraman Narayanamurthyc95b5b12010-08-31 13:19:48 -07001918
Sundarajan Srinivasand3514bb2013-12-04 17:02:00 -08001919 token = strtok(arg, ":");
1920 pname = token;
1921 token = strtok(NULL, ":");
1922 if(token)
1923 {
1924 lun = atoi(token);
1925 mmc_set_lun(lun);
1926 lun_set = true;
1927 }
1928
Mao Jinlong226f33a2014-07-04 17:24:10 +08001929 if (pname)
Greg Grisco6e754772011-06-23 12:19:39 -07001930 {
Mao Jinlong226f33a2014-07-04 17:24:10 +08001931 if (!strcmp(pname, "partition"))
1932 {
1933 dprintf(INFO, "Attempt to write partition image.\n");
1934 if (write_partition(sz, (unsigned char *) data)) {
1935 fastboot_fail("failed to write partition");
Greg Grisco6e754772011-06-23 12:19:39 -07001936 return;
1937 }
1938 }
Mao Jinlong226f33a2014-07-04 17:24:10 +08001939 else
Sundarajan Srinivasand3514bb2013-12-04 17:02:00 -08001940 {
Shashank Mittald3e54dd2014-08-28 15:24:02 -07001941#if VERIFIED_BOOT
1942 if(!strcmp(pname, KEYSTORE_PTN_NAME))
1943 {
1944 if(!device.is_unlocked)
1945 {
1946 fastboot_fail("unlock device to flash keystore");
1947 return;
1948 }
1949 if(!boot_verify_validate_keystore((unsigned char *)data))
1950 {
1951 fastboot_fail("image is not a keystore file");
1952 return;
1953 }
1954 }
1955#endif
Mao Jinlong226f33a2014-07-04 17:24:10 +08001956 index = partition_get_index(pname);
1957 ptn = partition_get_offset(index);
1958 if(ptn == 0) {
1959 fastboot_fail("partition table doesn't exist");
1960 return;
1961 }
Sundarajan Srinivasand3514bb2013-12-04 17:02:00 -08001962
Mao Jinlong226f33a2014-07-04 17:24:10 +08001963 if (!strcmp(pname, "boot") || !strcmp(pname, "recovery")) {
1964 if (memcmp((void *)data, BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
1965 fastboot_fail("image is not a boot image");
1966 return;
1967 }
1968 }
1969
1970 if(!lun_set)
1971 {
1972 lun = partition_get_lun(index);
1973 mmc_set_lun(lun);
1974 }
1975
1976 size = partition_get_size(index);
1977 if (ROUND_TO_PAGE(sz,511) > size) {
1978 fastboot_fail("size too large");
1979 return;
1980 }
1981 else if (mmc_write(ptn , sz, (unsigned int *)data)) {
1982 fastboot_fail("flash write failure");
1983 return;
1984 }
Greg Grisco6e754772011-06-23 12:19:39 -07001985 }
Shashank Mittal23b8f422010-04-16 19:27:21 -07001986 }
1987 fastboot_okay("");
1988 return;
1989}
1990
Ajay Dudani5c761132011-04-07 20:19:04 -07001991void cmd_flash_mmc_sparse_img(const char *arg, void *data, unsigned sz)
1992{
1993 unsigned int chunk;
1994 unsigned int chunk_data_sz;
Channagoud Kadabif627cf82013-09-09 14:08:20 -07001995 uint32_t *fill_buf = NULL;
1996 uint32_t fill_val;
1997 uint32_t chunk_blk_cnt = 0;
Ajay Dudani5c761132011-04-07 20:19:04 -07001998 sparse_header_t *sparse_header;
1999 chunk_header_t *chunk_header;
Ajay Dudaniab18f022011-05-12 14:39:22 -07002000 uint32_t total_blocks = 0;
Ajay Dudani5c761132011-04-07 20:19:04 -07002001 unsigned long long ptn = 0;
Channagoud Kadabi65b91002011-10-11 17:34:33 +05302002 unsigned long long size = 0;
Kinson Chikf1a43512011-07-14 11:28:39 -07002003 int index = INVALID_PTN;
Channagoud Kadabif627cf82013-09-09 14:08:20 -07002004 int i;
Sundarajan Srinivasand3514bb2013-12-04 17:02:00 -08002005 uint8_t lun = 0;
Ajay Dudani5c761132011-04-07 20:19:04 -07002006
Kinson Chikf1a43512011-07-14 11:28:39 -07002007 index = partition_get_index(arg);
2008 ptn = partition_get_offset(index);
2009 if(ptn == 0) {
Ajay Dudani5c761132011-04-07 20:19:04 -07002010 fastboot_fail("partition table doesn't exist");
2011 return;
2012 }
2013
Channagoud Kadabi65b91002011-10-11 17:34:33 +05302014 size = partition_get_size(index);
2015 if (ROUND_TO_PAGE(sz,511) > size) {
2016 fastboot_fail("size too large");
2017 return;
2018 }
2019
Sundarajan Srinivasand3514bb2013-12-04 17:02:00 -08002020 lun = partition_get_lun(index);
2021 mmc_set_lun(lun);
2022
Ajay Dudani5c761132011-04-07 20:19:04 -07002023 /* Read and skip over sparse image header */
2024 sparse_header = (sparse_header_t *) data;
Ajay Dudani876b3282012-12-21 14:12:17 -08002025 if ((sparse_header->total_blks * sparse_header->blk_sz) > size) {
2026 fastboot_fail("size too large");
2027 return;
2028 }
2029
Ajay Dudani5c761132011-04-07 20:19:04 -07002030 data += sparse_header->file_hdr_sz;
2031 if(sparse_header->file_hdr_sz > sizeof(sparse_header_t))
2032 {
2033 /* Skip the remaining bytes in a header that is longer than
2034 * we expected.
2035 */
2036 data += (sparse_header->file_hdr_sz - sizeof(sparse_header_t));
2037 }
2038
Ajay Dudanib06c05f2011-05-12 14:46:10 -07002039 dprintf (SPEW, "=== Sparse Image Header ===\n");
2040 dprintf (SPEW, "magic: 0x%x\n", sparse_header->magic);
2041 dprintf (SPEW, "major_version: 0x%x\n", sparse_header->major_version);
2042 dprintf (SPEW, "minor_version: 0x%x\n", sparse_header->minor_version);
2043 dprintf (SPEW, "file_hdr_sz: %d\n", sparse_header->file_hdr_sz);
2044 dprintf (SPEW, "chunk_hdr_sz: %d\n", sparse_header->chunk_hdr_sz);
2045 dprintf (SPEW, "blk_sz: %d\n", sparse_header->blk_sz);
2046 dprintf (SPEW, "total_blks: %d\n", sparse_header->total_blks);
2047 dprintf (SPEW, "total_chunks: %d\n", sparse_header->total_chunks);
Ajay Dudani5c761132011-04-07 20:19:04 -07002048
2049 /* Start processing chunks */
2050 for (chunk=0; chunk<sparse_header->total_chunks; chunk++)
2051 {
2052 /* Read and skip over chunk header */
2053 chunk_header = (chunk_header_t *) data;
2054 data += sizeof(chunk_header_t);
2055
2056 dprintf (SPEW, "=== Chunk Header ===\n");
2057 dprintf (SPEW, "chunk_type: 0x%x\n", chunk_header->chunk_type);
2058 dprintf (SPEW, "chunk_data_sz: 0x%x\n", chunk_header->chunk_sz);
2059 dprintf (SPEW, "total_size: 0x%x\n", chunk_header->total_sz);
2060
2061 if(sparse_header->chunk_hdr_sz > sizeof(chunk_header_t))
2062 {
2063 /* Skip the remaining bytes in a header that is longer than
2064 * we expected.
2065 */
2066 data += (sparse_header->chunk_hdr_sz - sizeof(chunk_header_t));
2067 }
2068
2069 chunk_data_sz = sparse_header->blk_sz * chunk_header->chunk_sz;
2070 switch (chunk_header->chunk_type)
2071 {
2072 case CHUNK_TYPE_RAW:
2073 if(chunk_header->total_sz != (sparse_header->chunk_hdr_sz +
2074 chunk_data_sz))
2075 {
2076 fastboot_fail("Bogus chunk size for chunk type Raw");
2077 return;
2078 }
2079
Ajay Dudaniab18f022011-05-12 14:39:22 -07002080 if(mmc_write(ptn + ((uint64_t)total_blocks*sparse_header->blk_sz),
2081 chunk_data_sz,
2082 (unsigned int*)data))
Ajay Dudani5c761132011-04-07 20:19:04 -07002083 {
2084 fastboot_fail("flash write failure");
2085 return;
2086 }
2087 total_blocks += chunk_header->chunk_sz;
2088 data += chunk_data_sz;
2089 break;
2090
Channagoud Kadabif627cf82013-09-09 14:08:20 -07002091 case CHUNK_TYPE_FILL:
2092 if(chunk_header->total_sz != (sparse_header->chunk_hdr_sz +
2093 sizeof(uint32_t)))
2094 {
2095 fastboot_fail("Bogus chunk size for chunk type FILL");
2096 return;
2097 }
2098
2099 fill_buf = (uint32_t *)memalign(CACHE_LINE, ROUNDUP(sparse_header->blk_sz, CACHE_LINE));
2100 if (!fill_buf)
2101 {
2102 fastboot_fail("Malloc failed for: CHUNK_TYPE_FILL");
2103 return;
2104 }
2105
2106 fill_val = *(uint32_t *)data;
2107 data = (char *) data + sizeof(uint32_t);
2108 chunk_blk_cnt = chunk_data_sz / sparse_header->blk_sz;
2109
2110 for (i = 0; i < (sparse_header->blk_sz / sizeof(fill_val)); i++)
2111 {
2112 fill_buf[i] = fill_val;
2113 }
2114
2115 for (i = 0; i < chunk_blk_cnt; i++)
2116 {
2117 if(mmc_write(ptn + ((uint64_t)total_blocks*sparse_header->blk_sz),
2118 sparse_header->blk_sz,
2119 fill_buf))
2120 {
2121 fastboot_fail("flash write failure");
2122 free(fill_buf);
2123 return;
2124 }
2125
2126 total_blocks++;
2127 }
2128
2129 free(fill_buf);
2130 break;
2131
Ajay Dudani5c761132011-04-07 20:19:04 -07002132 case CHUNK_TYPE_DONT_CARE:
Kinson Chik kchik@codeaurora.orgda29b1e2011-05-06 17:36:39 -07002133 total_blocks += chunk_header->chunk_sz;
2134 break;
2135
Ajay Dudani5c761132011-04-07 20:19:04 -07002136 case CHUNK_TYPE_CRC:
2137 if(chunk_header->total_sz != sparse_header->chunk_hdr_sz)
2138 {
2139 fastboot_fail("Bogus chunk size for chunk type Dont Care");
2140 return;
2141 }
2142 total_blocks += chunk_header->chunk_sz;
2143 data += chunk_data_sz;
2144 break;
2145
Kinson Chik kchik@codeaurora.orgda29b1e2011-05-06 17:36:39 -07002146 default:
Channagoud Kadabif627cf82013-09-09 14:08:20 -07002147 dprintf(CRITICAL, "Unkown chunk type: %x\n",chunk_header->chunk_type);
Ajay Dudani5c761132011-04-07 20:19:04 -07002148 fastboot_fail("Unknown chunk type");
2149 return;
2150 }
2151 }
2152
Ajay Dudani0c6927b2011-05-18 11:12:16 -07002153 dprintf(INFO, "Wrote %d blocks, expected to write %d blocks\n",
2154 total_blocks, sparse_header->total_blks);
2155
2156 if(total_blocks != sparse_header->total_blks)
2157 {
2158 fastboot_fail("sparse image write failure");
2159 }
Ajay Dudani5c761132011-04-07 20:19:04 -07002160
2161 fastboot_okay("");
2162 return;
2163}
2164
2165void cmd_flash_mmc(const char *arg, void *data, unsigned sz)
2166{
2167 sparse_header_t *sparse_header;
kchik@codeaurora.orgbce18ea2011-04-18 20:22:28 -07002168 /* 8 Byte Magic + 2048 Byte xml + Encrypted Data */
2169 unsigned int *magic_number = (unsigned int *) data;
Ajay Dudani5c761132011-04-07 20:19:04 -07002170
kchik@codeaurora.orgbce18ea2011-04-18 20:22:28 -07002171#ifdef SSD_ENABLE
sundarajan srinivasand4b1c482013-02-27 14:15:43 -08002172 int ret=0;
2173 uint32 major_version=0;
2174 uint32 minor_version=0;
2175
2176 ret = scm_svc_version(&major_version,&minor_version);
2177 if(!ret)
2178 {
2179 if(major_version >= 2)
2180 {
Amir Samuelovbb65ce02013-05-05 12:20:18 +03002181 if( !strcmp(arg, "ssd") || !strcmp(arg, "tqs") )
sundarajan srinivasand4b1c482013-02-27 14:15:43 -08002182 {
2183 ret = encrypt_scm((uint32 **) &data, &sz);
2184 if (ret != 0) {
2185 dprintf(CRITICAL, "ERROR: Encryption Failure\n");
2186 return;
2187 }
2188
Amir Samuelovbb65ce02013-05-05 12:20:18 +03002189 /* Protect only for SSD */
2190 if (!strcmp(arg, "ssd")) {
2191 ret = scm_protect_keystore((uint32 *) data, sz);
2192 if (ret != 0) {
2193 dprintf(CRITICAL, "ERROR: scm_protect_keystore Failed\n");
2194 return;
2195 }
sundarajan srinivasand4b1c482013-02-27 14:15:43 -08002196 }
2197 }
2198 else
2199 {
2200 ret = decrypt_scm_v2((uint32 **) &data, &sz);
2201 if(ret != 0)
2202 {
2203 dprintf(CRITICAL,"ERROR: Decryption Failure\n");
2204 return;
2205 }
2206 }
2207 }
2208 else
2209 {
2210 if (magic_number[0] == DECRYPT_MAGIC_0 &&
2211 magic_number[1] == DECRYPT_MAGIC_1)
2212 {
2213 ret = decrypt_scm((uint32 **) &data, &sz);
2214 if (ret != 0) {
2215 dprintf(CRITICAL, "ERROR: Invalid secure image\n");
2216 return;
2217 }
2218 }
2219 else if (magic_number[0] == ENCRYPT_MAGIC_0 &&
2220 magic_number[1] == ENCRYPT_MAGIC_1)
2221 {
2222 ret = encrypt_scm((uint32 **) &data, &sz);
2223 if (ret != 0) {
2224 dprintf(CRITICAL, "ERROR: Encryption Failure\n");
2225 return;
2226 }
2227 }
kchik@codeaurora.orgbce18ea2011-04-18 20:22:28 -07002228 }
2229 }
sundarajan srinivasand4b1c482013-02-27 14:15:43 -08002230 else
Neeti Desai127b9e02012-03-20 16:11:23 -07002231 {
sundarajan srinivasand4b1c482013-02-27 14:15:43 -08002232 dprintf(CRITICAL,"INVALID SVC Version\n");
2233 return;
Neeti Desai127b9e02012-03-20 16:11:23 -07002234 }
sundarajan srinivasand4b1c482013-02-27 14:15:43 -08002235#endif /* SSD_ENABLE */
Neeti Desai127b9e02012-03-20 16:11:23 -07002236
Shashank Mittald3e54dd2014-08-28 15:24:02 -07002237#if VERIFIED_BOOT
2238 if(!device.is_unlocked && !device.is_verified)
2239 {
2240 fastboot_fail("device is locked. Cannot flash images");
2241 return;
2242 }
2243 if(!device.is_unlocked && device.is_verified)
2244 {
2245 if(!boot_verify_flash_allowed(arg))
2246 {
2247 fastboot_fail("cannot flash this partition in verified state");
2248 return;
2249 }
2250 }
2251#endif
2252
kchik@codeaurora.orgbce18ea2011-04-18 20:22:28 -07002253 sparse_header = (sparse_header_t *) data;
Ajay Dudani5c761132011-04-07 20:19:04 -07002254 if (sparse_header->magic != SPARSE_HEADER_MAGIC)
2255 cmd_flash_mmc_img(arg, data, sz);
2256 else
2257 cmd_flash_mmc_sparse_img(arg, data, sz);
Ajay Dudani5c761132011-04-07 20:19:04 -07002258 return;
2259}
2260
Sridhar Parasurame94e8152014-10-24 14:06:03 -07002261void cmd_flash_nand(const char *arg, void *data, unsigned sz)
Dima Zavin214cc642009-01-26 11:16:21 -08002262{
2263 struct ptentry *ptn;
2264 struct ptable *ptable;
2265 unsigned extra = 0;
2266
2267 ptable = flash_get_ptable();
2268 if (ptable == NULL) {
2269 fastboot_fail("partition table doesn't exist");
2270 return;
2271 }
2272
2273 ptn = ptable_find(ptable, arg);
2274 if (ptn == NULL) {
2275 fastboot_fail("unknown partition name");
2276 return;
2277 }
2278
2279 if (!strcmp(ptn->name, "boot") || !strcmp(ptn->name, "recovery")) {
2280 if (memcmp((void *)data, BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
2281 fastboot_fail("image is not a boot image");
2282 return;
2283 }
2284 }
2285
Amol Jadi5c61a952012-05-04 17:05:35 -07002286 if (!strcmp(ptn->name, "system")
Deepa Dinamani13e32c42012-03-12 14:34:17 -07002287 || !strcmp(ptn->name, "userdata")
2288 || !strcmp(ptn->name, "persist")
Sundarajan Srinivasanb063a852013-11-19 14:02:27 -08002289 || !strcmp(ptn->name, "recoveryfs")
Sundarajan Srinivasan595b71e2013-11-05 12:44:34 -08002290 || !strcmp(ptn->name, "modem"))
2291 {
2292 if (memcmp((void *)data, UBI_MAGIC, UBI_MAGIC_SIZE))
Deepa Dinamaniea177912013-04-30 15:51:10 -07002293 extra = 1;
Sundarajan Srinivasan595b71e2013-11-05 12:44:34 -08002294 else
2295 extra = 0;
2296 }
2297 else
Shashank Mittaldcc2e352009-11-19 19:11:16 -08002298 sz = ROUND_TO_PAGE(sz, page_mask);
Dima Zavin214cc642009-01-26 11:16:21 -08002299
2300 dprintf(INFO, "writing %d bytes to '%s'\n", sz, ptn->name);
2301 if (flash_write(ptn, extra, data, sz)) {
2302 fastboot_fail("flash write failure");
2303 return;
2304 }
2305 dprintf(INFO, "partition '%s' updated\n", ptn->name);
2306 fastboot_okay("");
2307}
2308
Sridhar Parasurame94e8152014-10-24 14:06:03 -07002309void cmd_flash(const char *arg, void *data, unsigned sz)
2310{
2311 if(target_is_emmc_boot())
2312 cmd_flash_mmc(arg, data, sz);
2313 else
2314 cmd_flash_nand(arg, data, sz);
2315}
2316
Dima Zavin214cc642009-01-26 11:16:21 -08002317void cmd_continue(const char *arg, void *data, unsigned sz)
2318{
2319 fastboot_okay("");
Amol Jadi7c4316c2013-10-07 14:19:26 -07002320 fastboot_stop();
Shashank Mittald3e54dd2014-08-28 15:24:02 -07002321
Shashank Mittald8c42bf2010-06-09 15:44:28 -07002322 if (target_is_emmc_boot())
2323 {
2324 boot_linux_from_mmc();
2325 }
2326 else
2327 {
2328 boot_linux_from_flash();
2329 }
Dima Zavin214cc642009-01-26 11:16:21 -08002330}
2331
Chandan Uddaraju94183c02010-01-15 15:13:59 -08002332void cmd_reboot(const char *arg, void *data, unsigned sz)
2333{
Shashank Mittald8c42bf2010-06-09 15:44:28 -07002334 dprintf(INFO, "rebooting the device\n");
Chandan Uddaraju94183c02010-01-15 15:13:59 -08002335 fastboot_okay("");
2336 reboot_device(0);
2337}
2338
2339void cmd_reboot_bootloader(const char *arg, void *data, unsigned sz)
2340{
Shashank Mittald8c42bf2010-06-09 15:44:28 -07002341 dprintf(INFO, "rebooting the device\n");
Chandan Uddaraju94183c02010-01-15 15:13:59 -08002342 fastboot_okay("");
2343 reboot_device(FASTBOOT_MODE);
2344}
2345
Ameya Thakur11cf1a62013-08-05 12:44:48 -07002346void cmd_oem_enable_charger_screen(const char *arg, void *data, unsigned size)
2347{
2348 dprintf(INFO, "Enabling charger screen check\n");
2349 device.charger_screen_enabled = 1;
2350 write_device_info(&device);
2351 fastboot_okay("");
2352}
2353
2354void cmd_oem_disable_charger_screen(const char *arg, void *data, unsigned size)
2355{
2356 dprintf(INFO, "Disabling charger screen check\n");
2357 device.charger_screen_enabled = 0;
2358 write_device_info(&device);
2359 fastboot_okay("");
2360}
2361
Unnati Gandhi62c8ab82014-01-24 11:01:01 +05302362void cmd_oem_select_display_panel(const char *arg, void *data, unsigned size)
2363{
2364 dprintf(INFO, "Selecting display panel %s\n", arg);
2365 if (arg)
2366 strlcpy(device.display_panel, arg,
2367 sizeof(device.display_panel));
2368 write_device_info(&device);
2369 fastboot_okay("");
2370}
2371
Shashank Mittal162244e2011-08-08 19:01:25 -07002372void cmd_oem_unlock(const char *arg, void *data, unsigned sz)
2373{
Shashank Mittald3e54dd2014-08-28 15:24:02 -07002374 /* TODO: Wipe user data */
2375 if(!device.is_unlocked || device.is_verified)
Shashank Mittal162244e2011-08-08 19:01:25 -07002376 {
2377 device.is_unlocked = 1;
Shashank Mittald3e54dd2014-08-28 15:24:02 -07002378 device.is_verified = 0;
2379 write_device_info(&device);
2380 }
2381 fastboot_okay("");
2382}
2383
2384void cmd_oem_lock(const char *arg, void *data, unsigned sz)
2385{
2386 /* TODO: Wipe user data */
2387 if(device.is_unlocked || device.is_verified)
2388 {
2389 device.is_unlocked = 0;
2390 device.is_verified = 0;
2391 write_device_info(&device);
2392 }
2393 fastboot_okay("");
2394}
2395
2396void cmd_oem_verified(const char *arg, void *data, unsigned sz)
2397{
2398 /* TODO: Wipe user data */
2399 if(device.is_unlocked || !device.is_verified)
2400 {
2401 device.is_unlocked = 0;
2402 device.is_verified = 1;
Shashank Mittal162244e2011-08-08 19:01:25 -07002403 write_device_info(&device);
2404 }
2405 fastboot_okay("");
2406}
2407
Shashank Mittala0032282011-08-26 14:50:11 -07002408void cmd_oem_devinfo(const char *arg, void *data, unsigned sz)
2409{
Unnati Gandhi62c8ab82014-01-24 11:01:01 +05302410 char response[128];
Ameya Thakur11cf1a62013-08-05 12:44:48 -07002411 snprintf(response, sizeof(response), "\tDevice tampered: %s", (device.is_tampered ? "true" : "false"));
Shashank Mittala0032282011-08-26 14:50:11 -07002412 fastboot_info(response);
Ameya Thakur11cf1a62013-08-05 12:44:48 -07002413 snprintf(response, sizeof(response), "\tDevice unlocked: %s", (device.is_unlocked ? "true" : "false"));
2414 fastboot_info(response);
2415 snprintf(response, sizeof(response), "\tCharger screen enabled: %s", (device.charger_screen_enabled ? "true" : "false"));
Shashank Mittala0032282011-08-26 14:50:11 -07002416 fastboot_info(response);
Unnati Gandhi62c8ab82014-01-24 11:01:01 +05302417 snprintf(response, sizeof(response), "\tDisplay panel: %s", (device.display_panel));
2418 fastboot_info(response);
Shashank Mittala0032282011-08-26 14:50:11 -07002419 fastboot_okay("");
2420}
2421
Channagoud Kadabi4c4884e2013-04-09 17:12:13 -07002422void cmd_preflash(const char *arg, void *data, unsigned sz)
2423{
2424 fastboot_okay("");
2425}
2426
Aparna Mallavarapuad8c1ec2013-08-23 17:55:47 +05302427static struct fbimage logo_header = {0};
2428struct fbimage* splash_screen_flash();
2429
2430int splash_screen_check_header(struct fbimage *logo)
2431{
2432 if (memcmp(logo->header.magic, LOGO_IMG_MAGIC, 8))
2433 return -1;
2434 if (logo->header.width == 0 || logo->header.height == 0)
2435 return -1;
2436 return 0;
2437}
2438
2439struct fbimage* splash_screen_flash()
Chandan Uddaraju2943fd62010-06-21 10:56:39 -07002440{
2441 struct ptentry *ptn;
2442 struct ptable *ptable;
2443 struct fbcon_config *fb_display = NULL;
Aparna Mallavarapuad8c1ec2013-08-23 17:55:47 +05302444 struct fbimage *logo = &logo_header;
Chandan Uddaraju2943fd62010-06-21 10:56:39 -07002445
Aparna Mallavarapuad8c1ec2013-08-23 17:55:47 +05302446
2447 ptable = flash_get_ptable();
2448 if (ptable == NULL) {
2449 dprintf(CRITICAL, "ERROR: Partition table not found\n");
2450 return NULL;
2451 }
2452 ptn = ptable_find(ptable, "splash");
2453 if (ptn == NULL) {
2454 dprintf(CRITICAL, "ERROR: splash Partition not found\n");
2455 return NULL;
2456 }
2457
2458 if (flash_read(ptn, 0,(unsigned int *) logo, sizeof(logo->header))) {
2459 dprintf(CRITICAL, "ERROR: Cannot read boot image header\n");
2460 return NULL;
2461 }
2462
2463 if (splash_screen_check_header(logo)) {
2464 dprintf(CRITICAL, "ERROR: Boot image header invalid\n");
2465 return NULL;
2466 }
2467
2468 fb_display = fbcon_display();
2469 if (fb_display) {
Vineet Bajaj99291ed2014-09-09 12:29:46 +05302470 if ((logo->header.width != fb_display->width) || (logo->header.height != fb_display->height)) {
2471 dprintf(CRITICAL, "Logo config doesn't match with fb config. Fall back to default logo\n");
2472 return NULL;
Chandan Uddaraju2943fd62010-06-21 10:56:39 -07002473 }
Vineet Bajaj99291ed2014-09-09 12:29:46 +05302474 uint8_t *base = (uint8_t *) fb_display->base;
Aparna Mallavarapuad8c1ec2013-08-23 17:55:47 +05302475 if (flash_read(ptn + sizeof(logo->header), 0,
2476 base,
2477 ((((logo->header.width * logo->header.height * fb_display->bpp/8) + 511) >> 9) << 9))) {
2478 fbcon_clear();
Vineet Bajaj99291ed2014-09-09 12:29:46 +05302479 dprintf(CRITICAL, "ERROR: Cannot read splash image from partition\n");
Aparna Mallavarapuad8c1ec2013-08-23 17:55:47 +05302480 return NULL;
Chandan Uddaraju2943fd62010-06-21 10:56:39 -07002481 }
Aparna Mallavarapuad8c1ec2013-08-23 17:55:47 +05302482 logo->image = base;
2483 }
2484
2485 return logo;
2486}
2487
2488struct fbimage* splash_screen_mmc()
2489{
2490 int index = INVALID_PTN;
2491 unsigned long long ptn = 0;
2492 struct fbcon_config *fb_display = NULL;
2493 struct fbimage *logo = &logo_header;
2494
2495 index = partition_get_index("splash");
2496 if (index == 0) {
2497 dprintf(CRITICAL, "ERROR: splash Partition table not found\n");
2498 return NULL;
2499 }
2500
2501 ptn = partition_get_offset(index);
2502 if (ptn == 0) {
2503 dprintf(CRITICAL, "ERROR: splash Partition invalid\n");
2504 return NULL;
2505 }
2506
2507 if (mmc_read(ptn, (unsigned int *) logo, sizeof(logo->header))) {
2508 dprintf(CRITICAL, "ERROR: Cannot read splash image header\n");
2509 return NULL;
2510 }
2511
2512 if (splash_screen_check_header(logo)) {
2513 dprintf(CRITICAL, "ERROR: Splash image header invalid\n");
2514 return NULL;
2515 }
2516
2517 fb_display = fbcon_display();
2518 if (fb_display) {
Vineet Bajaj99291ed2014-09-09 12:29:46 +05302519 if ((logo->header.width != fb_display->width) || (logo->header.height != fb_display->height)) {
2520 dprintf(CRITICAL, "Logo config doesn't match with fb config. Fall back default logo\n");
2521 return NULL;
2522 }
Aparna Mallavarapuad8c1ec2013-08-23 17:55:47 +05302523 uint8_t *base = (uint8_t *) fb_display->base;
Aparna Mallavarapuad8c1ec2013-08-23 17:55:47 +05302524 if (mmc_read(ptn + sizeof(logo->header),
2525 base,
2526 ((((logo->header.width * logo->header.height * fb_display->bpp/8) + 511) >> 9) << 9))) {
2527 fbcon_clear();
Vineet Bajaj99291ed2014-09-09 12:29:46 +05302528 dprintf(CRITICAL, "ERROR: Cannot read splash image from partition\n");
Aparna Mallavarapuad8c1ec2013-08-23 17:55:47 +05302529 return NULL;
2530 }
2531
2532 logo->image = base;
2533 }
2534
2535 return logo;
2536}
2537
2538
2539struct fbimage* fetch_image_from_partition()
2540{
2541 if (target_is_emmc_boot()) {
2542 return splash_screen_mmc();
2543 } else {
2544 return splash_screen_flash();
Chandan Uddaraju2943fd62010-06-21 10:56:39 -07002545 }
2546}
2547
Channagoud Kadabi4c4884e2013-04-09 17:12:13 -07002548/* Get the size from partiton name */
2549static void get_partition_size(const char *arg, char *response)
2550{
2551 uint64_t ptn = 0;
2552 uint64_t size;
2553 int index = INVALID_PTN;
2554
2555 index = partition_get_index(arg);
2556
2557 if (index == INVALID_PTN)
2558 {
2559 dprintf(CRITICAL, "Invalid partition index\n");
2560 return;
2561 }
2562
2563 ptn = partition_get_offset(index);
2564
2565 if(!ptn)
2566 {
2567 dprintf(CRITICAL, "Invalid partition name %s\n", arg);
2568 return;
2569 }
2570
2571 size = partition_get_size(index);
2572
2573 snprintf(response, MAX_RSP_SIZE, "\t 0x%llx", size);
2574 return;
2575}
2576
2577/*
2578 * Publish the partition type & size info
2579 * fastboot getvar will publish the required information.
2580 * fastboot getvar partition_size:<partition_name>: partition size in hex
2581 * fastboot getvar partition_type:<partition_name>: partition type (ext/fat)
2582 */
2583static void publish_getvar_partition_info(struct getvar_partition_info *info, uint8_t num_parts)
2584{
2585 uint8_t i;
2586
2587 for (i = 0; i < num_parts; i++) {
2588 get_partition_size(info[i].part_name, info[i].size_response);
2589
2590 if (strlcat(info[i].getvar_size, info[i].part_name, MAX_GET_VAR_NAME_SIZE) >= MAX_GET_VAR_NAME_SIZE)
2591 {
2592 dprintf(CRITICAL, "partition size name truncated\n");
2593 return;
2594 }
2595 if (strlcat(info[i].getvar_type, info[i].part_name, MAX_GET_VAR_NAME_SIZE) >= MAX_GET_VAR_NAME_SIZE)
2596 {
2597 dprintf(CRITICAL, "partition type name truncated\n");
2598 return;
2599 }
2600
2601 /* publish partition size & type info */
2602 fastboot_publish((const char *) info[i].getvar_size, (const char *) info[i].size_response);
2603 fastboot_publish((const char *) info[i].getvar_type, (const char *) info[i].type_response);
2604 }
2605}
2606
Amol Jadi5edf3552013-07-23 14:15:34 -07002607/* register commands and variables for fastboot */
2608void aboot_fastboot_register_commands(void)
2609{
Sridhar Parasurame94e8152014-10-24 14:06:03 -07002610 int i;
Amol Jadi5edf3552013-07-23 14:15:34 -07002611
Sridhar Parasurame94e8152014-10-24 14:06:03 -07002612 struct fastboot_cmd_desc cmd_list[] = {
2613 /* By default the enabled list is empty. */
2614 {"", NULL},
2615 /* move commands enclosed within the below ifndef to here
2616 * if they need to be enabled in user build.
2617 */
2618#ifndef DISABLE_FASTBOOT_CMDS
2619 /* Register the following commands only for non-user builds */
2620 {"flash:", cmd_flash},
2621 {"erase:", cmd_erase},
2622 {"boot", cmd_boot},
2623 {"continue", cmd_continue},
2624 {"reboot", cmd_reboot},
2625 {"reboot-bootloader", cmd_reboot_bootloader},
2626 {"oem unlock", cmd_oem_unlock},
2627 {"oem lock", cmd_oem_lock},
2628 {"oem verified", cmd_oem_verified},
2629 {"oem device-info", cmd_oem_devinfo},
2630 {"preflash", cmd_preflash},
2631 {"oem enable-charger-screen", cmd_oem_enable_charger_screen},
2632 {"oem disable-charger-screen", cmd_oem_disable_charger_screen},
Aravind Venkateswaranbcca9b12014-11-04 17:04:01 -08002633 {"oem select-display-panel", cmd_oem_select_display_panel},
Sridhar Parasurame94e8152014-10-24 14:06:03 -07002634#endif
2635 };
2636
2637 int fastboot_cmds_count = sizeof(cmd_list)/sizeof(cmd_list[0]);
2638 for (i = 1; i < fastboot_cmds_count; i++)
2639 fastboot_register(cmd_list[i].name,cmd_list[i].cb);
2640
Amol Jadi5edf3552013-07-23 14:15:34 -07002641 /* publish variables and their values */
2642 fastboot_publish("product", TARGET(BOARD));
2643 fastboot_publish("kernel", "lk");
2644 fastboot_publish("serialno", sn_buf);
2645
2646 /*
2647 * partition info is supported only for emmc partitions
2648 * Calling this for NAND prints some error messages which
2649 * is harmless but misleading. Avoid calling this for NAND
2650 * devices.
2651 */
2652 if (target_is_emmc_boot())
2653 publish_getvar_partition_info(part_info, ARRAY_SIZE(part_info));
2654
2655 /* Max download size supported */
Ameya Thakur11cf1a62013-08-05 12:44:48 -07002656 snprintf(max_download_size, MAX_RSP_SIZE, "\t0x%x",
2657 target_get_max_flash_size());
Amol Jadi5edf3552013-07-23 14:15:34 -07002658 fastboot_publish("max-download-size", (const char *) max_download_size);
Ameya Thakur11cf1a62013-08-05 12:44:48 -07002659 /* Is the charger screen check enabled */
2660 snprintf(charger_screen_enabled, MAX_RSP_SIZE, "%d",
2661 device.charger_screen_enabled);
2662 fastboot_publish("charger-screen-enabled",
2663 (const char *) charger_screen_enabled);
Unnati Gandhi62c8ab82014-01-24 11:01:01 +05302664 snprintf(panel_display_mode, MAX_RSP_SIZE, "%s",
2665 device.display_panel);
2666 fastboot_publish("display-panel",
2667 (const char *) panel_display_mode);
Amol Jadi5edf3552013-07-23 14:15:34 -07002668}
2669
Brian Swetland9c4c0752009-01-25 16:23:50 -08002670void aboot_init(const struct app_descriptor *app)
2671{
Shashank Mittal4f99a882010-02-01 13:58:50 -08002672 unsigned reboot_mode = 0;
Pavel Nedev5d91d412013-04-29 11:34:24 +03002673 bool boot_into_fastboot = false;
Chandan Uddarajubedca152010-06-02 23:05:15 -07002674
Channagoud Kadabi749b0f82013-09-10 22:36:02 -07002675 /* Setup page size information for nv storage */
Shashank Mittald8c42bf2010-06-09 15:44:28 -07002676 if (target_is_emmc_boot())
2677 {
Channagoud Kadabi749b0f82013-09-10 22:36:02 -07002678 page_size = mmc_page_size();
Shashank Mittald8c42bf2010-06-09 15:44:28 -07002679 page_mask = page_size - 1;
2680 }
2681 else
2682 {
2683 page_size = flash_page_size();
2684 page_mask = page_size - 1;
2685 }
2686
Deepa Dinamani0e163a42013-05-24 17:08:15 -07002687 ASSERT((MEMBASE + MEMSIZE) > MEMBASE);
2688
Ameya Thakur11cf1a62013-08-05 12:44:48 -07002689 read_device_info(&device);
Shashank Mittal162244e2011-08-08 19:01:25 -07002690
Aravind Venkateswaran8f076242014-02-25 16:25:30 -08002691 /* Display splash screen if enabled */
2692#if DISPLAY_SPLASH_SCREEN
2693 dprintf(SPEW, "Display Init: Start\n");
Unnati Gandhi62c8ab82014-01-24 11:01:01 +05302694 target_display_init(device.display_panel);
Aravind Venkateswaran8f076242014-02-25 16:25:30 -08002695 dprintf(SPEW, "Display Init: Done\n");
2696#endif
2697
2698
Greg Griscod6250552011-06-29 14:40:23 -07002699 target_serialno((unsigned char *) sn_buf);
Ajay Dudanib06c05f2011-05-12 14:46:10 -07002700 dprintf(SPEW,"serial number: %s\n",sn_buf);
Subbaraman Narayanamurthyf17b4ae2011-02-16 20:19:56 -08002701
Dhaval Patel223ec952013-07-18 14:49:44 -07002702 memset(display_panel_buf, '\0', MAX_PANEL_BUF_SIZE);
2703
Matthew Qindefd5562014-07-11 18:02:40 +08002704 /*
2705 * Check power off reason if user force reset,
2706 * if yes phone will do normal boot.
2707 */
2708 if (is_user_force_reset())
2709 goto normal_boot;
2710
Chandan Uddaraju2943fd62010-06-21 10:56:39 -07002711 /* Check if we should do something other than booting up */
Ameya Thakur0b9c2442013-05-10 13:22:56 -07002712 if (keys_get_state(KEY_VOLUMEUP) && keys_get_state(KEY_VOLUMEDOWN))
Subbaraman Narayanamurthy0e445b02011-06-19 21:34:46 -07002713 {
Pavel Nedeva4c9d3a2013-05-15 14:42:34 +03002714 dprintf(ALWAYS,"dload mode key sequence detected\n");
2715 if (set_download_mode(EMERGENCY_DLOAD))
Ameya Thakur0b9c2442013-05-10 13:22:56 -07002716 {
Pavel Nedeva4c9d3a2013-05-15 14:42:34 +03002717 dprintf(CRITICAL,"dload mode not supported by target\n");
Ameya Thakur0b9c2442013-05-10 13:22:56 -07002718 }
2719 else
2720 {
Aparna Mallavarapu0751f7f2014-04-01 22:40:39 +05302721 reboot_device(DLOAD);
Pavel Nedeva4c9d3a2013-05-15 14:42:34 +03002722 dprintf(CRITICAL,"Failed to reboot into dload mode\n");
Ameya Thakur0b9c2442013-05-10 13:22:56 -07002723 }
2724 boot_into_fastboot = true;
2725 }
2726 if (!boot_into_fastboot)
2727 {
2728 if (keys_get_state(KEY_HOME) || keys_get_state(KEY_VOLUMEUP))
2729 boot_into_recovery = 1;
2730 if (!boot_into_recovery &&
2731 (keys_get_state(KEY_BACK) || keys_get_state(KEY_VOLUMEDOWN)))
Pavel Nedev5d91d412013-04-29 11:34:24 +03002732 boot_into_fastboot = true;
Subbaraman Narayanamurthy0e445b02011-06-19 21:34:46 -07002733 }
Shashank Mittald8c42bf2010-06-09 15:44:28 -07002734 #if NO_KEYPAD_DRIVER
Kinson Chik0b1c8162011-08-31 16:31:57 -07002735 if (fastboot_trigger())
Pavel Nedev5d91d412013-04-29 11:34:24 +03002736 boot_into_fastboot = true;
Shashank Mittald8c42bf2010-06-09 15:44:28 -07002737 #endif
Chandan Uddarajubedca152010-06-02 23:05:15 -07002738
Ajay Dudani77421292010-10-27 19:34:06 -07002739 reboot_mode = check_reboot_mode();
2740 if (reboot_mode == RECOVERY_MODE) {
2741 boot_into_recovery = 1;
2742 } else if(reboot_mode == FASTBOOT_MODE) {
Pavel Nedev5d91d412013-04-29 11:34:24 +03002743 boot_into_fastboot = true;
Matthew Qind886f3c2014-01-17 16:52:01 +08002744 } else if(reboot_mode == ALARM_BOOT) {
2745 boot_reason_alarm = true;
Ajay Dudani77421292010-10-27 19:34:06 -07002746 }
2747
Matthew Qindefd5562014-07-11 18:02:40 +08002748normal_boot:
Pavel Nedev5d91d412013-04-29 11:34:24 +03002749 if (!boot_into_fastboot)
Shashank Mittald8c42bf2010-06-09 15:44:28 -07002750 {
Pavel Nedev5d91d412013-04-29 11:34:24 +03002751 if (target_is_emmc_boot())
Shashank Mittala0032282011-08-26 14:50:11 -07002752 {
Pavel Nedev5d91d412013-04-29 11:34:24 +03002753 if(emmc_recovery_init())
2754 dprintf(ALWAYS,"error in emmc_recovery_init\n");
2755 if(target_use_signed_kernel())
Shashank Mittala0032282011-08-26 14:50:11 -07002756 {
Pavel Nedev5d91d412013-04-29 11:34:24 +03002757 if((device.is_unlocked) || (device.is_tampered))
2758 {
2759 #ifdef TZ_TAMPER_FUSE
2760 set_tamper_fuse_cmd();
2761 #endif
2762 #if USE_PCOM_SECBOOT
2763 set_tamper_flag(device.is_tampered);
2764 #endif
2765 }
Shashank Mittala0032282011-08-26 14:50:11 -07002766 }
Pavel Nedev5d91d412013-04-29 11:34:24 +03002767 boot_linux_from_mmc();
Shashank Mittala0032282011-08-26 14:50:11 -07002768 }
Pavel Nedev5d91d412013-04-29 11:34:24 +03002769 else
2770 {
2771 recovery_init();
2772 #if USE_PCOM_SECBOOT
2773 if((device.is_unlocked) || (device.is_tampered))
2774 set_tamper_flag(device.is_tampered);
2775 #endif
2776 boot_linux_from_flash();
2777 }
2778 dprintf(CRITICAL, "ERROR: Could not do normal boot. Reverting "
2779 "to fastboot mode.\n");
Shashank Mittald8c42bf2010-06-09 15:44:28 -07002780 }
Chandan Uddaraju2943fd62010-06-21 10:56:39 -07002781
Amol Jadi5edf3552013-07-23 14:15:34 -07002782 /* We are here means regular boot did not happen. Start fastboot. */
Channagoud Kadabi4c4884e2013-04-09 17:12:13 -07002783
Amol Jadi5edf3552013-07-23 14:15:34 -07002784 /* register aboot specific fastboot commands */
2785 aboot_fastboot_register_commands();
Amol Jadi57abe4c2011-05-24 15:47:27 -07002786
Amol Jadi5edf3552013-07-23 14:15:34 -07002787 /* dump partition table for debug info */
Kinson Chikf1a43512011-07-14 11:28:39 -07002788 partition_dump();
Amol Jadi5edf3552013-07-23 14:15:34 -07002789
2790 /* initialize and start fastboot */
2791 fastboot_init(target_get_scratch_address(), target_get_max_flash_size());
Brian Swetland9c4c0752009-01-25 16:23:50 -08002792}
2793
Deepa Dinamani41fa8d62013-05-23 13:25:36 -07002794uint32_t get_page_size()
2795{
2796 return page_size;
2797}
2798
Amir Samuelov57a6fa22013-06-05 16:36:43 +03002799/*
2800 * Calculated and save hash (SHA256) for non-signed boot image.
2801 *
Channagoud Kadabi82cf5c62014-08-24 22:17:34 -07002802 * @param image_addr - Boot image address
2803 * @param image_size - Size of the boot image
Amir Samuelov57a6fa22013-06-05 16:36:43 +03002804 *
2805 * @return int - 0 on success, negative value on failure.
2806 */
Channagoud Kadabi82cf5c62014-08-24 22:17:34 -07002807static int aboot_save_boot_hash_mmc(uint32_t image_addr, uint32_t image_size)
Amir Samuelov57a6fa22013-06-05 16:36:43 +03002808{
Channagoud Kadabi82cf5c62014-08-24 22:17:34 -07002809 unsigned int digest[8];
2810#if IMAGE_VERIF_ALGO_SHA1
2811 uint32_t auth_algo = CRYPTO_AUTH_ALG_SHA1;
2812#else
2813 uint32_t auth_algo = CRYPTO_AUTH_ALG_SHA256;
2814#endif
Amir Samuelov57a6fa22013-06-05 16:36:43 +03002815
Channagoud Kadabi82cf5c62014-08-24 22:17:34 -07002816 target_crypto_init_params();
2817 hash_find(image_addr, image_size, (unsigned char *)&digest, auth_algo);
Amir Samuelov57a6fa22013-06-05 16:36:43 +03002818
2819 save_kernel_hash_cmd(digest);
Channagoud Kadabi82cf5c62014-08-24 22:17:34 -07002820 dprintf(INFO, "aboot_save_boot_hash_mmc: imagesize_actual size %d bytes.\n", (int) image_size);
Amir Samuelov57a6fa22013-06-05 16:36:43 +03002821
2822 return 0;
2823}
2824
Brian Swetland9c4c0752009-01-25 16:23:50 -08002825APP_START(aboot)
2826 .init = aboot_init,
2827APP_END