blob: 8accda823d9aca7137c0a46d6f177dedcd623669 [file] [log] [blame]
Brian Swetland9c4c0752009-01-25 16:23:50 -08001/*
2 * Copyright (c) 2009, Google Inc.
3 * All rights reserved.
4 *
Channagoud Kadabia8c623f2015-01-13 14:48:48 -08005 * Copyright (c) 2009-2015, 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>
Tanya Brokhman1c94f1a2015-02-15 09:05:03 +020043#include <dev/flash-ubi.h>
Dima Zavin214cc642009-01-26 11:16:21 -080044#include <lib/ptable.h>
Dima Zavinb4283602009-01-26 16:36:57 -080045#include <dev/keys.h>
Shashank Mittal4f99a882010-02-01 13:58:50 -080046#include <dev/fbcon.h>
Ajay Dudanid04110c2011-01-17 23:55:07 -080047#include <baseband.h>
Greg Griscod6250552011-06-29 14:40:23 -070048#include <target.h>
49#include <mmc.h>
Kinson Chikf1a43512011-07-14 11:28:39 -070050#include <partition_parser.h>
Greg Griscod6250552011-06-29 14:40:23 -070051#include <platform.h>
Shashank Mittalcd98d472011-08-02 14:29:24 -070052#include <crypto_hash.h>
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -070053#include <malloc.h>
Amol Jadi492d5a52013-03-15 16:12:34 -070054#include <boot_stats.h>
Amir Samuelov57a6fa22013-06-05 16:36:43 +030055#include <sha.h>
Sundarajan Srinivasan3827a102013-09-10 13:57:40 -070056#include <platform/iomap.h>
Sundarajan Srinivasane52065a2014-03-20 16:25:59 -070057#include <boot_device.h>
Shashank Mittald3e54dd2014-08-28 15:24:02 -070058#include <boot_verifier.h>
Unnati Gandhi0c8e7c52014-07-17 14:33:09 +053059#include <image_verify.h>
Matthew Qinbb7923d2015-02-09 10:56:09 +080060#include <decompress.h>
Unnati Gandhi17b3bfc2015-05-11 12:58:16 +053061#include <platform/timer.h>
Channagoud Kadabi036c6052015-02-09 15:19:59 -080062#if USE_RPMB_FOR_DEVINFO
63#include <rpmb.h>
64#endif
Dima Zavin214cc642009-01-26 11:16:21 -080065
Neeti Desai17379b82012-06-04 18:42:53 -070066#if DEVICE_TREE
67#include <libfdt.h>
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -070068#include <dev_tree.h>
Neeti Desai17379b82012-06-04 18:42:53 -070069#endif
70
Aparna Mallavarapu118ccae2015-06-03 13:47:11 +053071#if WDOG_SUPPORT
72#include <wdog.h>
73#endif
74
Shashank Mittalcd98d472011-08-02 14:29:24 -070075#include "image_verify.h"
Shashank Mittal024c0332010-02-03 11:44:00 -080076#include "recovery.h"
Brian Swetland9c4c0752009-01-25 16:23:50 -080077#include "bootimg.h"
78#include "fastboot.h"
Ajay Dudani5c761132011-04-07 20:19:04 -070079#include "sparse_format.h"
Ajay Dudanide984792015-03-02 09:57:41 -080080#include "meta_format.h"
Greg Grisco6e754772011-06-23 12:19:39 -070081#include "mmc.h"
Shashank Mittal162244e2011-08-08 19:01:25 -070082#include "devinfo.h"
Neeti Desai465491e2012-07-31 12:53:35 -070083#include "board.h"
Shashank Mittal162244e2011-08-08 19:01:25 -070084#include "scm.h"
Amit Blay6281ebc2015-01-11 14:44:08 +020085#include "mdtp.h"
kchik@codeaurora.orgbce18ea2011-04-18 20:22:28 -070086
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -070087extern bool target_use_signed_kernel(void);
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -070088extern void platform_uninit(void);
Channagoud Kadabi33defe22013-06-18 18:35:40 -070089extern void target_uninit(void);
Joonwoo Park61112782013-10-02 19:50:39 -070090extern int get_target_boot_params(const char *cmdline, const char *part,
91 char *buf, int buflen);
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -070092
Sridhar Parasuram7e16d172015-07-05 11:35:23 -070093void *info_buf;
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -070094void write_device_info_mmc(device_info *dev);
95void write_device_info_flash(device_info *dev);
Channagoud Kadabi82cf5c62014-08-24 22:17:34 -070096static int aboot_save_boot_hash_mmc(uint32_t image_addr, uint32_t image_size);
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -070097
Sridhar Parasurame94e8152014-10-24 14:06:03 -070098/* fastboot command function pointer */
99typedef void (*fastboot_cmd_fn) (const char *, void *, unsigned);
100
101struct fastboot_cmd_desc {
102 char * name;
103 fastboot_cmd_fn cb;
104};
105
Subbaraman Narayanamurthyeb92bcc2010-07-20 14:32:46 -0700106#define EXPAND(NAME) #NAME
107#define TARGET(NAME) EXPAND(NAME)
Brian Swetland2defe162009-08-18 14:35:59 -0700108
Ajay Dudanicd01f9b2010-02-23 21:13:04 -0800109#ifdef MEMBASE
110#define EMMC_BOOT_IMG_HEADER_ADDR (0xFF000+(MEMBASE))
111#else
David Ng183a7422009-12-07 14:55:21 -0800112#define EMMC_BOOT_IMG_HEADER_ADDR 0xFF000
Ajay Dudanicd01f9b2010-02-23 21:13:04 -0800113#endif
114
Deepa Dinamani0e163a42013-05-24 17:08:15 -0700115#ifndef MEMSIZE
116#define MEMSIZE 1024*1024
117#endif
118
119#define MAX_TAGS_SIZE 1024
120
lijuang72875802015-02-10 10:35:12 +0800121#define RECOVERY_HARD_RESET_MODE 0x01
122#define FASTBOOT_HARD_RESET_MODE 0x02
123#define RTC_HARD_RESET_MODE 0x03
124
Chandan Uddarajude85d3f2010-01-05 16:32:33 -0800125#define RECOVERY_MODE 0x77665502
126#define FASTBOOT_MODE 0x77665500
Matthew Qind886f3c2014-01-17 16:52:01 +0800127#define ALARM_BOOT 0x77665503
Chandan Uddarajude85d3f2010-01-05 16:32:33 -0800128
Kun Liang2f1601a2013-08-12 16:29:54 +0800129/* make 4096 as default size to ensure EFS,EXT4's erasing */
130#define DEFAULT_ERASE_SIZE 4096
Kuogee Hsieh55e92c52013-12-20 08:34:10 -0800131#define MAX_PANEL_BUF_SIZE 128
Kun Liang2f1601a2013-08-12 16:29:54 +0800132
Dhaval Patelf83d73b2014-06-23 16:24:37 -0700133#define DISPLAY_DEFAULT_PREFIX "mdss_mdp"
Sundarajan Srinivasane52065a2014-03-20 16:25:59 -0700134#define BOOT_DEV_MAX_LEN 64
Sundarajan Srinivasan595b71e2013-11-05 12:44:34 -0800135
Abhimanyu Kapur0f79d572014-02-19 22:03:02 -0800136#define IS_ARM64(ptr) (ptr->magic_64 == KERNEL64_HDR_MAGIC) ? true : false
137
Channagoud Kadabifc3b31f2014-06-18 17:41:01 -0700138#define ADD_OF(a, b) (UINT_MAX - b > a) ? (a + b) : UINT_MAX
139
Sridhar Parasuram7bd4aaf2015-02-12 11:14:38 -0800140#if USE_BOOTDEV_CMDLINE
Sundarajan Srinivasane52065a2014-03-20 16:25:59 -0700141static const char *emmc_cmdline = " androidboot.bootdevice=";
Sundarajan Srinivasan3827a102013-09-10 13:57:40 -0700142#else
David Ng183a7422009-12-07 14:55:21 -0800143static const char *emmc_cmdline = " androidboot.emmc=true";
Sundarajan Srinivasan3827a102013-09-10 13:57:40 -0700144#endif
Subbaraman Narayanamurthyf17b4ae2011-02-16 20:19:56 -0800145static const char *usb_sn_cmdline = " androidboot.serialno=";
Pavel Nedev328ac822013-04-05 15:25:11 +0300146static const char *androidboot_mode = " androidboot.mode=";
Matthew Qind886f3c2014-01-17 16:52:01 +0800147static const char *alarmboot_cmdline = " androidboot.alarmboot=true";
Pavel Nedev898298c2013-02-27 12:36:09 -0800148static const char *loglevel = " quiet";
Ajay Dudanica3a33c2011-11-18 08:31:40 -0800149static const char *battchg_pause = " androidboot.mode=charger";
Shashank Mittalcd98d472011-08-02 14:29:24 -0700150static const char *auth_kernel = " androidboot.authorized_kernel=true";
Pavel Nedev5614d222013-06-17 18:01:02 +0300151static const char *secondary_gpt_enable = " gpt";
Shay Nachmanibc10dfe2015-02-10 14:45:55 +0200152static const char *mdtp_activated_flag = " mdtp";
David Ng183a7422009-12-07 14:55:21 -0800153
Ajay Dudani6cff85e2011-02-04 16:02:16 -0800154static const char *baseband_apq = " androidboot.baseband=apq";
155static const char *baseband_msm = " androidboot.baseband=msm";
156static const char *baseband_csfb = " androidboot.baseband=csfb";
157static const char *baseband_svlte2a = " androidboot.baseband=svlte2a";
Ajay Dudani403bc492011-09-30 16:17:21 -0700158static const char *baseband_mdm = " androidboot.baseband=mdm";
Sundarajan Srinivasanaaa8aff2013-11-12 17:19:14 -0800159static const char *baseband_mdm2 = " androidboot.baseband=mdm2";
Amol Jadi5c61a952012-05-04 17:05:35 -0700160static const char *baseband_sglte = " androidboot.baseband=sglte";
Amol Jadi2a15a272013-01-22 12:03:36 -0800161static const char *baseband_dsda = " androidboot.baseband=dsda";
162static const char *baseband_dsda2 = " androidboot.baseband=dsda2";
sundarajan srinivasanf8e9f3f2013-03-04 15:56:58 -0800163static const char *baseband_sglte2 = " androidboot.baseband=sglte2";
Hanumant Singh8e1ac232014-01-29 13:41:51 -0800164static const char *warmboot_cmdline = " qpnp-power-on.warm_boot=1";
Ajay Dudanid04110c2011-01-17 23:55:07 -0800165
Deepa Dinamani41fa8d62013-05-23 13:25:36 -0700166static unsigned page_size = 0;
167static unsigned page_mask = 0;
168static char ffbm_mode_string[FFBM_MODE_BUF_SIZE];
169static bool boot_into_ffbm;
Joonwoo Park61112782013-10-02 19:50:39 -0700170static char target_boot_params[64];
Matthew Qind886f3c2014-01-17 16:52:01 +0800171static bool boot_reason_alarm;
Channagoud Kadabi80a182b2015-03-11 17:04:23 -0700172static bool devinfo_present = true;
Deepa Dinamani41fa8d62013-05-23 13:25:36 -0700173
Shashank Mittalcd98d472011-08-02 14:29:24 -0700174/* Assuming unauthorized kernel image by default */
175static int auth_kernel_img = 0;
176
Channagoud Kadabiaafbbfc2015-03-04 17:52:56 -0800177static device_info device = {DEVICE_MAGIC, 0, 0, 0, 0, {0}, {0},{0}};
vijay kumarc65876c2015-04-24 13:29:16 +0530178static bool is_allow_unlock = 0;
Shashank Mittal162244e2011-08-08 19:01:25 -0700179
Dima Zavin42168f22009-01-30 11:52:22 -0800180struct atag_ptbl_entry
181{
182 char name[16];
183 unsigned offset;
184 unsigned size;
185 unsigned flags;
186};
187
Channagoud Kadabi4c4884e2013-04-09 17:12:13 -0700188/*
189 * Partition info, required to be published
190 * for fastboot
191 */
192struct getvar_partition_info {
193 const char part_name[MAX_GPT_NAME_SIZE]; /* Partition name */
194 char getvar_size[MAX_GET_VAR_NAME_SIZE]; /* fastboot get var name for size */
195 char getvar_type[MAX_GET_VAR_NAME_SIZE]; /* fastboot get var name for type */
196 char size_response[MAX_RSP_SIZE]; /* fastboot response for size */
197 char type_response[MAX_RSP_SIZE]; /* fastboot response for type */
198};
199
200/*
201 * Right now, we are publishing the info for only
202 * three partitions
203 */
204struct getvar_partition_info part_info[] =
205{
206 { "system" , "partition-size:", "partition-type:", "", "ext4" },
207 { "userdata", "partition-size:", "partition-type:", "", "ext4" },
208 { "cache" , "partition-size:", "partition-type:", "", "ext4" },
209};
210
211char max_download_size[MAX_RSP_SIZE];
Ameya Thakur11cf1a62013-08-05 12:44:48 -0700212char charger_screen_enabled[MAX_RSP_SIZE];
Subbaraman Narayanamurthyf17b4ae2011-02-16 20:19:56 -0800213char sn_buf[13];
Dhaval Patel223ec952013-07-18 14:49:44 -0700214char display_panel_buf[MAX_PANEL_BUF_SIZE];
Unnati Gandhi62c8ab82014-01-24 11:01:01 +0530215char panel_display_mode[MAX_RSP_SIZE];
Greg Griscod6250552011-06-29 14:40:23 -0700216
Greg Griscod2471ef2011-07-14 13:00:42 -0700217extern int emmc_recovery_init(void);
218
Kinson Chik0b1c8162011-08-31 16:31:57 -0700219#if NO_KEYPAD_DRIVER
220extern int fastboot_trigger(void);
221#endif
Greg Griscod2471ef2011-07-14 13:00:42 -0700222
Abhimanyu Kapur0f79d572014-02-19 22:03:02 -0800223static void update_ker_tags_rdisk_addr(struct boot_img_hdr *hdr, bool is_arm64)
Channagoud Kadabia22144f2013-03-20 11:49:01 -0700224{
225 /* overwrite the destination of specified for the project */
Channagoud Kadabi7042fa32013-04-26 16:44:14 -0700226#ifdef ABOOT_IGNORE_BOOT_HEADER_ADDRS
Abhimanyu Kapur0f79d572014-02-19 22:03:02 -0800227 if (is_arm64)
228 hdr->kernel_addr = ABOOT_FORCE_KERNEL64_ADDR;
229 else
230 hdr->kernel_addr = ABOOT_FORCE_KERNEL_ADDR;
Channagoud Kadabi7042fa32013-04-26 16:44:14 -0700231 hdr->ramdisk_addr = ABOOT_FORCE_RAMDISK_ADDR;
232 hdr->tags_addr = ABOOT_FORCE_TAGS_ADDR;
Channagoud Kadabia22144f2013-03-20 11:49:01 -0700233#endif
234}
235
Dima Zavin42168f22009-01-30 11:52:22 -0800236static void ptentry_to_tag(unsigned **ptr, struct ptentry *ptn)
237{
238 struct atag_ptbl_entry atag_ptn;
239
240 memcpy(atag_ptn.name, ptn->name, 16);
241 atag_ptn.name[15] = '\0';
242 atag_ptn.offset = ptn->start;
243 atag_ptn.size = ptn->length;
244 atag_ptn.flags = ptn->flags;
245 memcpy(*ptr, &atag_ptn, sizeof(struct atag_ptbl_entry));
246 *ptr += sizeof(struct atag_ptbl_entry) / sizeof(unsigned);
247}
Brian Swetland9c4c0752009-01-25 16:23:50 -0800248
Neeti Desaie245d492012-06-01 12:52:13 -0700249unsigned char *update_cmdline(const char * cmdline)
Brian Swetland9c4c0752009-01-25 16:23:50 -0800250{
David Ng183a7422009-12-07 14:55:21 -0800251 int cmdline_len = 0;
252 int have_cmdline = 0;
Amol Jadi168b7712012-03-06 16:15:00 -0800253 unsigned char *cmdline_final = NULL;
Neeti Desaie245d492012-06-01 12:52:13 -0700254 int pause_at_bootup = 0;
Hanumant Singh8e1ac232014-01-29 13:41:51 -0800255 bool warm_boot = false;
Pavel Nedev5614d222013-06-17 18:01:02 +0300256 bool gpt_exists = partition_gpt_exists();
Joonwoo Park61112782013-10-02 19:50:39 -0700257 int have_target_boot_params = 0;
Sundarajan Srinivasane52065a2014-03-20 16:25:59 -0700258 char *boot_dev_buf = NULL;
Shay Nachmanibc10dfe2015-02-10 14:45:55 +0200259 bool is_mdtp_activated = 0;
260#ifdef MDTP_SUPPORT
261 mdtp_activated(&is_mdtp_activated);
262#endif /* MDTP_SUPPORT */
Dima Zavin42168f22009-01-30 11:52:22 -0800263
Brian Swetland9c4c0752009-01-25 16:23:50 -0800264 if (cmdline && cmdline[0]) {
David Ng183a7422009-12-07 14:55:21 -0800265 cmdline_len = strlen(cmdline);
266 have_cmdline = 1;
267 }
268 if (target_is_emmc_boot()) {
269 cmdline_len += strlen(emmc_cmdline);
Sridhar Parasuram7bd4aaf2015-02-12 11:14:38 -0800270#if USE_BOOTDEV_CMDLINE
Sundarajan Srinivasane52065a2014-03-20 16:25:59 -0700271 boot_dev_buf = (char *) malloc(sizeof(char) * BOOT_DEV_MAX_LEN);
272 ASSERT(boot_dev_buf);
273 platform_boot_dev_cmdline(boot_dev_buf);
274 cmdline_len += strlen(boot_dev_buf);
Sundarajan Srinivasan3827a102013-09-10 13:57:40 -0700275#endif
David Ng183a7422009-12-07 14:55:21 -0800276 }
Subbaraman Narayanamurthyf17b4ae2011-02-16 20:19:56 -0800277
278 cmdline_len += strlen(usb_sn_cmdline);
279 cmdline_len += strlen(sn_buf);
280
Pavel Nedev5614d222013-06-17 18:01:02 +0300281 if (boot_into_recovery && gpt_exists)
282 cmdline_len += strlen(secondary_gpt_enable);
283
Shay Nachmanibc10dfe2015-02-10 14:45:55 +0200284 if(is_mdtp_activated)
285 cmdline_len += strlen(mdtp_activated_flag);
286
Pavel Nedev328ac822013-04-05 15:25:11 +0300287 if (boot_into_ffbm) {
288 cmdline_len += strlen(androidboot_mode);
Deepa Dinamani41fa8d62013-05-23 13:25:36 -0700289 cmdline_len += strlen(ffbm_mode_string);
Pavel Nedev898298c2013-02-27 12:36:09 -0800290 /* reduce kernel console messages to speed-up boot */
291 cmdline_len += strlen(loglevel);
Matthew Qind886f3c2014-01-17 16:52:01 +0800292 } else if (boot_reason_alarm) {
293 cmdline_len += strlen(alarmboot_cmdline);
Ameya Thakur11cf1a62013-08-05 12:44:48 -0700294 } else if (device.charger_screen_enabled &&
295 target_pause_for_battery_charge()) {
David Ngf773dde2010-07-26 19:55:08 -0700296 pause_at_bootup = 1;
297 cmdline_len += strlen(battchg_pause);
298 }
Ajay Dudanid04110c2011-01-17 23:55:07 -0800299
Shashank Mittalcd98d472011-08-02 14:29:24 -0700300 if(target_use_signed_kernel() && auth_kernel_img) {
301 cmdline_len += strlen(auth_kernel);
302 }
303
Joonwoo Park61112782013-10-02 19:50:39 -0700304 if (get_target_boot_params(cmdline, boot_into_recovery ? "recoveryfs" :
305 "system",
306 target_boot_params,
307 sizeof(target_boot_params)) == 0) {
308 have_target_boot_params = 1;
309 cmdline_len += strlen(target_boot_params);
310 }
311
Ajay Dudanid04110c2011-01-17 23:55:07 -0800312 /* Determine correct androidboot.baseband to use */
313 switch(target_baseband())
314 {
315 case BASEBAND_APQ:
316 cmdline_len += strlen(baseband_apq);
317 break;
318
319 case BASEBAND_MSM:
320 cmdline_len += strlen(baseband_msm);
321 break;
322
323 case BASEBAND_CSFB:
324 cmdline_len += strlen(baseband_csfb);
325 break;
326
Ajay Dudani6cff85e2011-02-04 16:02:16 -0800327 case BASEBAND_SVLTE2A:
328 cmdline_len += strlen(baseband_svlte2a);
Ajay Dudanid04110c2011-01-17 23:55:07 -0800329 break;
Ajay Dudani403bc492011-09-30 16:17:21 -0700330
331 case BASEBAND_MDM:
332 cmdline_len += strlen(baseband_mdm);
333 break;
Amol Jadi5c61a952012-05-04 17:05:35 -0700334
Sundarajan Srinivasanaaa8aff2013-11-12 17:19:14 -0800335 case BASEBAND_MDM2:
336 cmdline_len += strlen(baseband_mdm2);
337 break;
338
Amol Jadi5c61a952012-05-04 17:05:35 -0700339 case BASEBAND_SGLTE:
340 cmdline_len += strlen(baseband_sglte);
341 break;
Channagoud Kadabi141f2982012-10-31 11:23:02 +0530342
sundarajan srinivasanf8e9f3f2013-03-04 15:56:58 -0800343 case BASEBAND_SGLTE2:
344 cmdline_len += strlen(baseband_sglte2);
345 break;
346
Channagoud Kadabi141f2982012-10-31 11:23:02 +0530347 case BASEBAND_DSDA:
348 cmdline_len += strlen(baseband_dsda);
349 break;
Amol Jadi2a15a272013-01-22 12:03:36 -0800350
351 case BASEBAND_DSDA2:
352 cmdline_len += strlen(baseband_dsda2);
353 break;
Ajay Dudanid04110c2011-01-17 23:55:07 -0800354 }
355
Lijuan Gao4a5b8322014-07-24 10:38:42 +0800356 if (cmdline) {
357 if ((strstr(cmdline, DISPLAY_DEFAULT_PREFIX) == NULL) &&
358 target_display_panel_node(device.display_panel,
359 display_panel_buf, MAX_PANEL_BUF_SIZE) &&
360 strlen(display_panel_buf)) {
361 cmdline_len += strlen(display_panel_buf);
362 }
Dhaval Patel223ec952013-07-18 14:49:44 -0700363 }
364
Hanumant Singh8e1ac232014-01-29 13:41:51 -0800365 if (target_warm_boot()) {
366 warm_boot = true;
367 cmdline_len += strlen(warmboot_cmdline);
368 }
369
David Ng183a7422009-12-07 14:55:21 -0800370 if (cmdline_len > 0) {
371 const char *src;
Maria Yu52254c02014-07-04 16:14:54 +0800372 unsigned char *dst;
373
374 cmdline_final = (unsigned char*) malloc((cmdline_len + 4) & (~3));
375 ASSERT(cmdline_final != NULL);
376 dst = cmdline_final;
Neeti Desaie245d492012-06-01 12:52:13 -0700377
Amol Jadi168b7712012-03-06 16:15:00 -0800378 /* Save start ptr for debug print */
David Ng183a7422009-12-07 14:55:21 -0800379 if (have_cmdline) {
380 src = cmdline;
381 while ((*dst++ = *src++));
382 }
383 if (target_is_emmc_boot()) {
384 src = emmc_cmdline;
385 if (have_cmdline) --dst;
David Ngf773dde2010-07-26 19:55:08 -0700386 have_cmdline = 1;
387 while ((*dst++ = *src++));
Sridhar Parasuram7bd4aaf2015-02-12 11:14:38 -0800388#if USE_BOOTDEV_CMDLINE
Sundarajan Srinivasane52065a2014-03-20 16:25:59 -0700389 src = boot_dev_buf;
390 if (have_cmdline) --dst;
391 while ((*dst++ = *src++));
392#endif
David Ngf773dde2010-07-26 19:55:08 -0700393 }
Subbaraman Narayanamurthyf17b4ae2011-02-16 20:19:56 -0800394
395 src = usb_sn_cmdline;
396 if (have_cmdline) --dst;
397 have_cmdline = 1;
398 while ((*dst++ = *src++));
399 src = sn_buf;
400 if (have_cmdline) --dst;
401 have_cmdline = 1;
402 while ((*dst++ = *src++));
Hanumant Singh8e1ac232014-01-29 13:41:51 -0800403 if (warm_boot) {
404 if (have_cmdline) --dst;
405 src = warmboot_cmdline;
406 while ((*dst++ = *src++));
407 }
Subbaraman Narayanamurthyf17b4ae2011-02-16 20:19:56 -0800408
Pavel Nedev5614d222013-06-17 18:01:02 +0300409 if (boot_into_recovery && gpt_exists) {
410 src = secondary_gpt_enable;
411 if (have_cmdline) --dst;
412 while ((*dst++ = *src++));
413 }
414
Shay Nachmanibc10dfe2015-02-10 14:45:55 +0200415 if (is_mdtp_activated) {
416 src = mdtp_activated_flag;
417 if (have_cmdline) --dst;
418 while ((*dst++ = *src++));
419 }
420
Pavel Nedev328ac822013-04-05 15:25:11 +0300421 if (boot_into_ffbm) {
422 src = androidboot_mode;
423 if (have_cmdline) --dst;
424 while ((*dst++ = *src++));
Deepa Dinamani41fa8d62013-05-23 13:25:36 -0700425 src = ffbm_mode_string;
Pavel Nedev328ac822013-04-05 15:25:11 +0300426 if (have_cmdline) --dst;
427 while ((*dst++ = *src++));
Pavel Nedev898298c2013-02-27 12:36:09 -0800428 src = loglevel;
429 if (have_cmdline) --dst;
430 while ((*dst++ = *src++));
Matthew Qind886f3c2014-01-17 16:52:01 +0800431 } else if (boot_reason_alarm) {
432 src = alarmboot_cmdline;
433 if (have_cmdline) --dst;
434 while ((*dst++ = *src++));
Pavel Nedev328ac822013-04-05 15:25:11 +0300435 } else if (pause_at_bootup) {
David Ngf773dde2010-07-26 19:55:08 -0700436 src = battchg_pause;
437 if (have_cmdline) --dst;
David Ng183a7422009-12-07 14:55:21 -0800438 while ((*dst++ = *src++));
439 }
Ajay Dudanid04110c2011-01-17 23:55:07 -0800440
Shashank Mittalcd98d472011-08-02 14:29:24 -0700441 if(target_use_signed_kernel() && auth_kernel_img) {
442 src = auth_kernel;
443 if (have_cmdline) --dst;
444 while ((*dst++ = *src++));
445 }
446
Ajay Dudanid04110c2011-01-17 23:55:07 -0800447 switch(target_baseband())
448 {
449 case BASEBAND_APQ:
450 src = baseband_apq;
451 if (have_cmdline) --dst;
452 while ((*dst++ = *src++));
453 break;
454
455 case BASEBAND_MSM:
456 src = baseband_msm;
457 if (have_cmdline) --dst;
458 while ((*dst++ = *src++));
459 break;
460
461 case BASEBAND_CSFB:
462 src = baseband_csfb;
463 if (have_cmdline) --dst;
464 while ((*dst++ = *src++));
465 break;
466
Ajay Dudani6cff85e2011-02-04 16:02:16 -0800467 case BASEBAND_SVLTE2A:
468 src = baseband_svlte2a;
Ajay Dudanid04110c2011-01-17 23:55:07 -0800469 if (have_cmdline) --dst;
470 while ((*dst++ = *src++));
471 break;
Ajay Dudani403bc492011-09-30 16:17:21 -0700472
473 case BASEBAND_MDM:
474 src = baseband_mdm;
475 if (have_cmdline) --dst;
476 while ((*dst++ = *src++));
477 break;
Amol Jadi5c61a952012-05-04 17:05:35 -0700478
Sundarajan Srinivasanaaa8aff2013-11-12 17:19:14 -0800479 case BASEBAND_MDM2:
480 src = baseband_mdm2;
481 if (have_cmdline) --dst;
482 while ((*dst++ = *src++));
483 break;
484
Amol Jadi5c61a952012-05-04 17:05:35 -0700485 case BASEBAND_SGLTE:
486 src = baseband_sglte;
487 if (have_cmdline) --dst;
488 while ((*dst++ = *src++));
489 break;
Channagoud Kadabi141f2982012-10-31 11:23:02 +0530490
sundarajan srinivasanf8e9f3f2013-03-04 15:56:58 -0800491 case BASEBAND_SGLTE2:
492 src = baseband_sglte2;
493 if (have_cmdline) --dst;
494 while ((*dst++ = *src++));
495 break;
496
Channagoud Kadabi141f2982012-10-31 11:23:02 +0530497 case BASEBAND_DSDA:
498 src = baseband_dsda;
499 if (have_cmdline) --dst;
500 while ((*dst++ = *src++));
501 break;
Amol Jadi2a15a272013-01-22 12:03:36 -0800502
503 case BASEBAND_DSDA2:
504 src = baseband_dsda2;
505 if (have_cmdline) --dst;
506 while ((*dst++ = *src++));
507 break;
Ajay Dudanid04110c2011-01-17 23:55:07 -0800508 }
Dhaval Patel223ec952013-07-18 14:49:44 -0700509
510 if (strlen(display_panel_buf)) {
Dhaval Patel223ec952013-07-18 14:49:44 -0700511 src = display_panel_buf;
512 if (have_cmdline) --dst;
513 while ((*dst++ = *src++));
514 }
Joonwoo Park61112782013-10-02 19:50:39 -0700515
516 if (have_target_boot_params) {
517 if (have_cmdline) --dst;
518 src = target_boot_params;
519 while ((*dst++ = *src++));
520 }
Neeti Desaie245d492012-06-01 12:52:13 -0700521 }
Dhaval Patel223ec952013-07-18 14:49:44 -0700522
523
Sundarajan Srinivasane52065a2014-03-20 16:25:59 -0700524 if (boot_dev_buf)
525 free(boot_dev_buf);
526
Veera Sundaram Sankaranf9915462014-12-09 11:54:59 -0800527 if (cmdline_final)
528 dprintf(INFO, "cmdline: %s\n", cmdline_final);
529 else
530 dprintf(INFO, "cmdline is NULL\n");
Neeti Desaie245d492012-06-01 12:52:13 -0700531 return cmdline_final;
532}
533
534unsigned *atag_core(unsigned *ptr)
535{
536 /* CORE */
537 *ptr++ = 2;
538 *ptr++ = 0x54410001;
539
540 return ptr;
541
542}
543
544unsigned *atag_ramdisk(unsigned *ptr, void *ramdisk,
545 unsigned ramdisk_size)
546{
547 if (ramdisk_size) {
548 *ptr++ = 4;
549 *ptr++ = 0x54420005;
550 *ptr++ = (unsigned)ramdisk;
551 *ptr++ = ramdisk_size;
Brian Swetland9c4c0752009-01-25 16:23:50 -0800552 }
553
Neeti Desaie245d492012-06-01 12:52:13 -0700554 return ptr;
555}
556
557unsigned *atag_ptable(unsigned **ptr_addr)
558{
559 int i;
560 struct ptable *ptable;
561
562 if ((ptable = flash_get_ptable()) && (ptable->count != 0)) {
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -0700563 *(*ptr_addr)++ = 2 + (ptable->count * (sizeof(struct atag_ptbl_entry) /
564 sizeof(unsigned)));
Neeti Desaie245d492012-06-01 12:52:13 -0700565 *(*ptr_addr)++ = 0x4d534d70;
566 for (i = 0; i < ptable->count; ++i)
567 ptentry_to_tag(ptr_addr, ptable_get(ptable, i));
568 }
569
570 return (*ptr_addr);
571}
572
573unsigned *atag_cmdline(unsigned *ptr, const char *cmdline)
574{
575 int cmdline_length = 0;
576 int n;
Neeti Desaie245d492012-06-01 12:52:13 -0700577 char *dest;
578
Amol Jadi10c7d1c2013-01-25 13:24:29 -0800579 cmdline_length = strlen((const char*)cmdline);
Neeti Desaie245d492012-06-01 12:52:13 -0700580 n = (cmdline_length + 4) & (~3);
581
582 *ptr++ = (n / 4) + 2;
583 *ptr++ = 0x54410009;
584 dest = (char *) ptr;
Amol Jadi10c7d1c2013-01-25 13:24:29 -0800585 while ((*dest++ = *cmdline++));
Neeti Desaie245d492012-06-01 12:52:13 -0700586 ptr += (n / 4);
587
588 return ptr;
589}
590
591unsigned *atag_end(unsigned *ptr)
592{
Brian Swetland9c4c0752009-01-25 16:23:50 -0800593 /* END */
594 *ptr++ = 0;
595 *ptr++ = 0;
596
Neeti Desaie245d492012-06-01 12:52:13 -0700597 return ptr;
598}
599
600void generate_atags(unsigned *ptr, const char *cmdline,
601 void *ramdisk, unsigned ramdisk_size)
602{
603
604 ptr = atag_core(ptr);
605 ptr = atag_ramdisk(ptr, ramdisk, ramdisk_size);
606 ptr = target_atag_mem(ptr);
607
608 /* Skip NAND partition ATAGS for eMMC boot */
609 if (!target_is_emmc_boot()){
610 ptr = atag_ptable(&ptr);
611 }
612
613 ptr = atag_cmdline(ptr, cmdline);
614 ptr = atag_end(ptr);
615}
616
Deepa Dinamani0bf2f442012-10-19 11:41:06 -0700617typedef void entry_func_ptr(unsigned, unsigned, unsigned*);
Neeti Desaie245d492012-06-01 12:52:13 -0700618void boot_linux(void *kernel, unsigned *tags,
619 const char *cmdline, unsigned machtype,
620 void *ramdisk, unsigned ramdisk_size)
621{
Amol Jadi10c7d1c2013-01-25 13:24:29 -0800622 unsigned char *final_cmdline;
Amol Jadib6be5c12012-11-14 13:39:51 -0800623#if DEVICE_TREE
Neeti Desai17379b82012-06-04 18:42:53 -0700624 int ret = 0;
Amol Jadib6be5c12012-11-14 13:39:51 -0800625#endif
626
Deepa Dinamani0bf2f442012-10-19 11:41:06 -0700627 void (*entry)(unsigned, unsigned, unsigned*) = (entry_func_ptr*)(PA((addr_t)kernel));
Deepa Dinamani25a9f762012-11-30 15:57:15 -0800628 uint32_t tags_phys = PA((addr_t)tags);
Abhimanyu Kapur0f79d572014-02-19 22:03:02 -0800629 struct kernel64_hdr *kptr = (struct kernel64_hdr*)kernel;
Deepa Dinamani25a9f762012-11-30 15:57:15 -0800630
Unnati Gandhi0c8e7c52014-07-17 14:33:09 +0530631 ramdisk = (void *)PA((addr_t)ramdisk);
Neeti Desaie245d492012-06-01 12:52:13 -0700632
Amol Jadi10c7d1c2013-01-25 13:24:29 -0800633 final_cmdline = update_cmdline((const char*)cmdline);
634
Neeti Desai17379b82012-06-04 18:42:53 -0700635#if DEVICE_TREE
Amol Jadib6be5c12012-11-14 13:39:51 -0800636 dprintf(INFO, "Updating device tree: start\n");
637
Neeti Desai17379b82012-06-04 18:42:53 -0700638 /* Update the Device Tree */
Unnati Gandhi0c8e7c52014-07-17 14:33:09 +0530639 ret = update_device_tree((void *)tags,(const char *)final_cmdline, ramdisk, ramdisk_size);
Neeti Desai17379b82012-06-04 18:42:53 -0700640 if(ret)
641 {
642 dprintf(CRITICAL, "ERROR: Updating Device Tree Failed \n");
643 ASSERT(0);
644 }
Amol Jadib6be5c12012-11-14 13:39:51 -0800645 dprintf(INFO, "Updating device tree: done\n");
Neeti Desai17379b82012-06-04 18:42:53 -0700646#else
Neeti Desaie245d492012-06-01 12:52:13 -0700647 /* Generating the Atags */
Amol Jadi10c7d1c2013-01-25 13:24:29 -0800648 generate_atags(tags, final_cmdline, ramdisk, ramdisk_size);
Neeti Desai17379b82012-06-04 18:42:53 -0700649#endif
Neeti Desaie245d492012-06-01 12:52:13 -0700650
Maria Yu52254c02014-07-04 16:14:54 +0800651 free(final_cmdline);
Channagoud Kadabi5d0371c2014-10-21 22:27:07 -0700652
653#if VERIFIED_BOOT
654 /* Write protect the device info */
Channagoud Kadabi3bd9d1e2015-05-05 16:18:20 -0700655 if (!boot_into_recovery && target_build_variant_user() && devinfo_present && mmc_write_protect("devinfo", 1))
Channagoud Kadabi5d0371c2014-10-21 22:27:07 -0700656 {
657 dprintf(INFO, "Failed to write protect dev info\n");
658 ASSERT(0);
659 }
660#endif
661
Channagoud Kadabi33defe22013-06-18 18:35:40 -0700662 /* Perform target specific cleanup */
663 target_uninit();
664
Aravind Venkateswaran8f076242014-02-25 16:25:30 -0800665 /* Turn off splash screen if enabled */
666#if DISPLAY_SPLASH_SCREEN
667 target_display_shutdown();
668#endif
669
670
Deepa Dinamani33734bc2013-03-06 12:16:06 -0800671 dprintf(INFO, "booting linux @ %p, ramdisk @ %p (%d), tags/device tree @ %p\n",
Unnati Gandhi0c8e7c52014-07-17 14:33:09 +0530672 entry, ramdisk, ramdisk_size, (void *)tags_phys);
Brian Swetland9c4c0752009-01-25 16:23:50 -0800673
674 enter_critical_section();
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -0700675
Aparna Mallavarapu118ccae2015-06-03 13:47:11 +0530676 /* Initialise wdog to catch early kernel crashes */
677#if WDOG_SUPPORT
678 msm_wdog_init();
679#endif
Amol Jadi4421e652011-06-16 15:00:48 -0700680 /* do any platform specific cleanup before kernel entry */
681 platform_uninit();
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -0700682
Brian Swetland9c4c0752009-01-25 16:23:50 -0800683 arch_disable_cache(UCACHE);
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -0700684
Amol Jadi504f9fe2012-08-16 13:56:48 -0700685#if ARM_WITH_MMU
Brian Swetland9c4c0752009-01-25 16:23:50 -0800686 arch_disable_mmu();
Amol Jadi504f9fe2012-08-16 13:56:48 -0700687#endif
Amol Jadi492d5a52013-03-15 16:12:34 -0700688 bs_set_timestamp(BS_KERNEL_ENTRY);
Abhimanyu Kapur0f79d572014-02-19 22:03:02 -0800689
690 if (IS_ARM64(kptr))
691 /* Jump to a 64bit kernel */
692 scm_elexec_call((paddr_t)kernel, tags_phys);
693 else
694 /* Jump to a 32bit kernel */
695 entry(0, machtype, (unsigned*)tags_phys);
Brian Swetland9c4c0752009-01-25 16:23:50 -0800696}
697
Deepa Dinamani0e163a42013-05-24 17:08:15 -0700698/* Function to check if the memory address range falls within the aboot
699 * boundaries.
700 * start: Start of the memory region
701 * size: Size of the memory region
702 */
703int check_aboot_addr_range_overlap(uint32_t start, uint32_t size)
704{
705 /* Check for boundary conditions. */
Sundarajan Srinivasance2a0ea2013-12-16 17:02:56 -0800706 if ((UINT_MAX - start) < size)
Deepa Dinamani0e163a42013-05-24 17:08:15 -0700707 return -1;
708
709 /* Check for memory overlap. */
710 if ((start < MEMBASE) && ((start + size) <= MEMBASE))
711 return 0;
Channagoud Kadabi94143912013-10-15 12:53:52 -0700712 else if (start >= (MEMBASE + MEMSIZE))
Deepa Dinamani0e163a42013-05-24 17:08:15 -0700713 return 0;
714 else
715 return -1;
716}
717
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800718#define ROUND_TO_PAGE(x,y) (((x) + (y)) & (~(y)))
Brian Swetland9c4c0752009-01-25 16:23:50 -0800719
Abhimanyu Kapur0f79d572014-02-19 22:03:02 -0800720BUF_DMA_ALIGN(buf, BOOT_IMG_MAX_PAGE_SIZE); //Equal to max-supported pagesize
Amol Jadib6be5c12012-11-14 13:39:51 -0800721#if DEVICE_TREE
Abhimanyu Kapur0f79d572014-02-19 22:03:02 -0800722BUF_DMA_ALIGN(dt_buf, BOOT_IMG_MAX_PAGE_SIZE);
Amol Jadib6be5c12012-11-14 13:39:51 -0800723#endif
Dima Zavin214cc642009-01-26 11:16:21 -0800724
Deepa Dinamani0e163a42013-05-24 17:08:15 -0700725static void verify_signed_bootimg(uint32_t bootimg_addr, uint32_t bootimg_size)
726{
727 int ret;
Channagoud Kadabia8c623f2015-01-13 14:48:48 -0800728
729#if !VERIFIED_BOOT
Sundarajan Srinivasance54d6e2013-11-11 12:45:00 -0800730#if IMAGE_VERIF_ALGO_SHA1
731 uint32_t auth_algo = CRYPTO_AUTH_ALG_SHA1;
732#else
733 uint32_t auth_algo = CRYPTO_AUTH_ALG_SHA256;
734#endif
Channagoud Kadabia8c623f2015-01-13 14:48:48 -0800735#endif
Deepa Dinamani0e163a42013-05-24 17:08:15 -0700736
737 /* Assume device is rooted at this time. */
738 device.is_tampered = 1;
739
740 dprintf(INFO, "Authenticating boot image (%d): start\n", bootimg_size);
741
Shashank Mittald3e54dd2014-08-28 15:24:02 -0700742#if VERIFIED_BOOT
743 if(boot_into_recovery)
744 {
745 ret = boot_verify_image((unsigned char *)bootimg_addr,
Unnati Gandhi47051252015-03-02 15:21:09 +0530746 bootimg_size, "/recovery");
Shashank Mittald3e54dd2014-08-28 15:24:02 -0700747 }
748 else
749 {
750 ret = boot_verify_image((unsigned char *)bootimg_addr,
Unnati Gandhi47051252015-03-02 15:21:09 +0530751 bootimg_size, "/boot");
Shashank Mittald3e54dd2014-08-28 15:24:02 -0700752 }
753 boot_verify_print_state();
754#else
Deepa Dinamani0e163a42013-05-24 17:08:15 -0700755 ret = image_verify((unsigned char *)bootimg_addr,
756 (unsigned char *)(bootimg_addr + bootimg_size),
757 bootimg_size,
Sundarajan Srinivasance54d6e2013-11-11 12:45:00 -0800758 auth_algo);
Shashank Mittald3e54dd2014-08-28 15:24:02 -0700759#endif
Deepa Dinamani0e163a42013-05-24 17:08:15 -0700760 dprintf(INFO, "Authenticating boot image: done return value = %d\n", ret);
761
762 if (ret)
763 {
764 /* Authorized kernel */
765 device.is_tampered = 0;
Sundarajan Srinivasan3fb21f12013-09-16 18:36:15 -0700766 auth_kernel_img = 1;
Deepa Dinamani0e163a42013-05-24 17:08:15 -0700767 }
768
Amit Blay4aa292f2015-04-28 21:55:59 +0300769#ifdef MDTP_SUPPORT
770 {
771 /* Verify MDTP lock.
772 * For boot & recovery partitions, use aboot's verification result.
773 */
774 mdtp_ext_partition_verification_t ext_partition;
775 ext_partition.partition = boot_into_recovery ? MDTP_PARTITION_RECOVERY : MDTP_PARTITION_BOOT;
776 ext_partition.integrity_state = device.is_tampered ? MDTP_PARTITION_STATE_INVALID : MDTP_PARTITION_STATE_VALID;
777 ext_partition.page_size = 0; /* Not needed since already validated */
778 ext_partition.image_addr = 0; /* Not needed since already validated */
779 ext_partition.image_size = 0; /* Not needed since already validated */
780 ext_partition.sig_avail = FALSE; /* Not needed since already validated */
781 mdtp_fwlock_verify_lock(&ext_partition);
782 }
783#endif /* MDTP_SUPPORT */
784
Deepa Dinamani0e163a42013-05-24 17:08:15 -0700785#if USE_PCOM_SECBOOT
786 set_tamper_flag(device.is_tampered);
787#endif
788
Shashank Mittald3e54dd2014-08-28 15:24:02 -0700789#if VERIFIED_BOOT
790 if(boot_verify_get_state() == RED)
791 {
792 if(!boot_into_recovery)
793 {
794 dprintf(CRITICAL,
795 "Device verification failed. Rebooting into recovery.\n");
Unnati Gandhi17b3bfc2015-05-11 12:58:16 +0530796 mdelay(1000);
Shashank Mittald3e54dd2014-08-28 15:24:02 -0700797 reboot_device(RECOVERY_MODE);
798 }
799 else
800 {
801 dprintf(CRITICAL,
802 "Recovery image verification failed. Asserting..\n");
803 ASSERT(0);
804 }
805 }
806#endif
Unnati Gandhi1be04752015-03-27 19:41:53 +0530807
808 if(device.is_tampered)
809 {
810 write_device_info_mmc(&device);
811 #ifdef TZ_TAMPER_FUSE
812 set_tamper_fuse_cmd();
813 #endif
814 #ifdef ASSERT_ON_TAMPER
815 dprintf(CRITICAL, "Device is tampered. Asserting..\n");
816 ASSERT(0);
817 #endif
818 }
819
Deepa Dinamani0e163a42013-05-24 17:08:15 -0700820}
821
Maunik Shah0f3c8ac2014-03-02 17:47:58 +0530822static bool check_format_bit()
823{
824 bool ret = false;
825 int index;
826 uint64_t offset;
827 struct boot_selection_info *in = NULL;
828 char *buf = NULL;
829
830 index = partition_get_index("bootselect");
831 if (index == INVALID_PTN)
832 {
833 dprintf(INFO, "Unable to locate /bootselect partition\n");
834 return ret;
835 }
836 offset = partition_get_offset(index);
837 if(!offset)
838 {
839 dprintf(INFO, "partition /bootselect doesn't exist\n");
840 return ret;
841 }
842 buf = (char *) memalign(CACHE_LINE, ROUNDUP(page_size, CACHE_LINE));
843 ASSERT(buf);
Unnati Gandhi0c8e7c52014-07-17 14:33:09 +0530844 if (mmc_read(offset, (uint32_t *)buf, page_size))
Maunik Shah0f3c8ac2014-03-02 17:47:58 +0530845 {
846 dprintf(INFO, "mmc read failure /bootselect %d\n", page_size);
847 free(buf);
848 return ret;
849 }
850 in = (struct boot_selection_info *) buf;
851 if ((in->signature == BOOTSELECT_SIGNATURE) &&
852 (in->version == BOOTSELECT_VERSION)) {
853 if ((in->state_info & BOOTSELECT_FORMAT) &&
854 !(in->state_info & BOOTSELECT_FACTORY))
855 ret = true;
856 } else {
857 dprintf(CRITICAL, "Signature: 0x%08x or version: 0x%08x mismatched of /bootselect\n",
858 in->signature, in->version);
859 ASSERT(0);
860 }
861 free(buf);
862 return ret;
863}
864
Shashank Mittald3e54dd2014-08-28 15:24:02 -0700865void boot_verifier_init()
866{
Shashank Mittald3e54dd2014-08-28 15:24:02 -0700867 uint32_t boot_state;
868 /* Check if device unlock */
869 if(device.is_unlocked)
870 {
871 boot_verify_send_event(DEV_UNLOCK);
872 boot_verify_print_state();
873 dprintf(CRITICAL, "Device is unlocked! Skipping verification...\n");
874 return;
875 }
876 else
877 {
878 boot_verify_send_event(BOOT_INIT);
879 }
880
881 /* Initialize keystore */
882 boot_state = boot_verify_keystore_init();
883 if(boot_state == YELLOW)
884 {
885 boot_verify_print_state();
886 dprintf(CRITICAL, "Keystore verification failed! Continuing anyways...\n");
887 }
888}
889
Shashank Mittal23b8f422010-04-16 19:27:21 -0700890int boot_linux_from_mmc(void)
891{
892 struct boot_img_hdr *hdr = (void*) buf;
893 struct boot_img_hdr *uhdr;
894 unsigned offset = 0;
Deepa Dinamani41fa8d62013-05-23 13:25:36 -0700895 int rcode;
Shashank Mittal23b8f422010-04-16 19:27:21 -0700896 unsigned long long ptn = 0;
Kinson Chikf1a43512011-07-14 11:28:39 -0700897 int index = INVALID_PTN;
Shashank Mittal23b8f422010-04-16 19:27:21 -0700898
Shashank Mittalcd98d472011-08-02 14:29:24 -0700899 unsigned char *image_addr = 0;
900 unsigned kernel_actual;
901 unsigned ramdisk_actual;
902 unsigned imagesize_actual;
Neeti Desai465491e2012-07-31 12:53:35 -0700903 unsigned second_actual = 0;
Neeti Desai465491e2012-07-31 12:53:35 -0700904
Matthew Qin271927e2015-03-31 22:07:07 -0400905 unsigned int dtb_size = 0;
Matthew Qinbb7923d2015-02-09 10:56:09 +0800906 unsigned int out_len = 0;
907 unsigned int out_avai_len = 0;
908 unsigned char *out_addr = NULL;
909 uint32_t dtb_offset = 0;
910 unsigned char *kernel_start_addr = NULL;
911 unsigned int kernel_size = 0;
912 int rc;
913
Neeti Desai465491e2012-07-31 12:53:35 -0700914#if DEVICE_TREE
915 struct dt_table *table;
Joel Kingaa335dc2013-06-03 16:11:08 -0700916 struct dt_entry dt_entry;
Neeti Desai465491e2012-07-31 12:53:35 -0700917 unsigned dt_table_offset;
Deepa Dinamani7aaf83d2012-12-21 11:27:01 -0800918 uint32_t dt_actual;
Deepa Dinamani19648b42013-09-05 17:05:55 -0700919 uint32_t dt_hdr_size;
Matthew Qin271927e2015-03-31 22:07:07 -0400920 unsigned char *best_match_dt_addr = NULL;
Neeti Desai465491e2012-07-31 12:53:35 -0700921#endif
Matthew Qin49e51fa2015-02-09 10:40:45 +0800922 struct kernel64_hdr *kptr = NULL;
Abhimanyu Kapur0f79d572014-02-19 22:03:02 -0800923
Maunik Shah0f3c8ac2014-03-02 17:47:58 +0530924 if (check_format_bit())
925 boot_into_recovery = 1;
926
Deepa Dinamani41fa8d62013-05-23 13:25:36 -0700927 if (!boot_into_recovery) {
928 memset(ffbm_mode_string, '\0', sizeof(ffbm_mode_string));
929 rcode = get_ffbm(ffbm_mode_string, sizeof(ffbm_mode_string));
930 if (rcode <= 0) {
931 boot_into_ffbm = false;
932 if (rcode < 0)
933 dprintf(CRITICAL,"failed to get ffbm cookie");
934 } else
935 boot_into_ffbm = true;
936 } else
937 boot_into_ffbm = false;
Shashank Mittal23b8f422010-04-16 19:27:21 -0700938 uhdr = (struct boot_img_hdr *)EMMC_BOOT_IMG_HEADER_ADDR;
939 if (!memcmp(uhdr->magic, BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
940 dprintf(INFO, "Unified boot method!\n");
941 hdr = uhdr;
942 goto unified_boot;
943 }
Greg Griscod6250552011-06-29 14:40:23 -0700944 if (!boot_into_recovery) {
Kinson Chikf1a43512011-07-14 11:28:39 -0700945 index = partition_get_index("boot");
946 ptn = partition_get_offset(index);
947 if(ptn == 0) {
Shashank Mittal85b91f62010-10-30 10:12:38 -0700948 dprintf(CRITICAL, "ERROR: No boot partition found\n");
949 return -1;
950 }
Kinson Chikf1a43512011-07-14 11:28:39 -0700951 }
952 else {
953 index = partition_get_index("recovery");
954 ptn = partition_get_offset(index);
955 if(ptn == 0) {
Shashank Mittal85b91f62010-10-30 10:12:38 -0700956 dprintf(CRITICAL, "ERROR: No recovery partition found\n");
957 return -1;
958 }
Shashank Mittal23b8f422010-04-16 19:27:21 -0700959 }
Channagoud Kadabief0547c2015-02-10 12:57:38 -0800960 /* Set Lun for boot & recovery partitions */
961 mmc_set_lun(partition_get_lun(index));
Shashank Mittal23b8f422010-04-16 19:27:21 -0700962
Unnati Gandhi0c8e7c52014-07-17 14:33:09 +0530963 if (mmc_read(ptn + offset, (uint32_t *) buf, page_size)) {
Shashank Mittal23b8f422010-04-16 19:27:21 -0700964 dprintf(CRITICAL, "ERROR: Cannot read boot image header\n");
965 return -1;
966 }
Shashank Mittal23b8f422010-04-16 19:27:21 -0700967
968 if (memcmp(hdr->magic, BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
Kinson Chik kchik@codeaurora.org82e4ae62011-04-12 17:42:07 -0700969 dprintf(CRITICAL, "ERROR: Invalid boot image header\n");
Shashank Mittal23b8f422010-04-16 19:27:21 -0700970 return -1;
971 }
972
Subbaraman Narayanamurthyfbe13a02010-09-10 11:51:12 -0700973 if (hdr->page_size && (hdr->page_size != page_size)) {
vijay kumar2e21b3a2014-06-26 17:40:15 +0530974
975 if (hdr->page_size > BOOT_IMG_MAX_PAGE_SIZE) {
976 dprintf(CRITICAL, "ERROR: Invalid page size\n");
977 return -1;
978 }
Subbaraman Narayanamurthyfbe13a02010-09-10 11:51:12 -0700979 page_size = hdr->page_size;
980 page_mask = page_size - 1;
Shashank Mittal23b8f422010-04-16 19:27:21 -0700981 }
982
Matthew Qin49e51fa2015-02-09 10:40:45 +0800983 kernel_actual = ROUND_TO_PAGE(hdr->kernel_size, page_mask);
984 ramdisk_actual = ROUND_TO_PAGE(hdr->ramdisk_size, page_mask);
Abhimanyu Kapur0f79d572014-02-19 22:03:02 -0800985
Matthew Qin49e51fa2015-02-09 10:40:45 +0800986 image_addr = (unsigned char *)target_get_scratch_address();
987
988#if DEVICE_TREE
989 dt_actual = ROUND_TO_PAGE(hdr->dt_size, page_mask);
990 imagesize_actual = (page_size + kernel_actual + ramdisk_actual + dt_actual);
991#else
992 imagesize_actual = (page_size + kernel_actual + ramdisk_actual);
993#endif
994
995#if VERIFIED_BOOT
996 boot_verifier_init();
997#endif
998
999 if (check_aboot_addr_range_overlap((uint32_t) image_addr, imagesize_actual))
1000 {
1001 dprintf(CRITICAL, "Boot image buffer address overlaps with aboot addresses.\n");
1002 return -1;
1003 }
1004
Matthew Qinbb7923d2015-02-09 10:56:09 +08001005 /*
1006 * Update loading flow of bootimage to support compressed/uncompressed
1007 * bootimage on both 64bit and 32bit platform.
1008 * 1. Load bootimage from emmc partition onto DDR.
1009 * 2. Check if bootimage is gzip format. If yes, decompress compressed kernel
1010 * 3. Check kernel header and update kernel load addr for 64bit and 32bit
1011 * platform accordingly.
1012 * 4. Sanity Check on kernel_addr and ramdisk_addr and copy data.
1013 */
1014
Matthew Qin49e51fa2015-02-09 10:40:45 +08001015 dprintf(INFO, "Loading boot image (%d): start\n", imagesize_actual);
1016 bs_set_timestamp(BS_KERNEL_LOAD_START);
1017
Matthew Qinbb7923d2015-02-09 10:56:09 +08001018 /* Read image without signature */
Matthew Qin49e51fa2015-02-09 10:40:45 +08001019 if (mmc_read(ptn + offset, (void *)image_addr, imagesize_actual))
1020 {
1021 dprintf(CRITICAL, "ERROR: Cannot read boot image\n");
1022 return -1;
1023 }
1024
1025 dprintf(INFO, "Loading boot image (%d): done\n", imagesize_actual);
1026 bs_set_timestamp(BS_KERNEL_LOAD_DONE);
1027
1028 /* Authenticate Kernel */
1029 dprintf(INFO, "use_signed_kernel=%d, is_unlocked=%d, is_tampered=%d.\n",
1030 (int) target_use_signed_kernel(),
1031 device.is_unlocked,
1032 device.is_tampered);
1033
1034 if(target_use_signed_kernel() && (!device.is_unlocked))
1035 {
1036 offset = imagesize_actual;
1037 if (check_aboot_addr_range_overlap((uint32_t)image_addr + offset, page_size))
1038 {
1039 dprintf(CRITICAL, "Signature read buffer address overlaps with aboot addresses.\n");
1040 return -1;
1041 }
1042
1043 /* Read signature */
1044 if(mmc_read(ptn + offset, (void *)(image_addr + offset), page_size))
1045 {
1046 dprintf(CRITICAL, "ERROR: Cannot read boot image signature\n");
1047 return -1;
1048 }
1049
1050 verify_signed_bootimg((uint32_t)image_addr, imagesize_actual);
1051 } else {
1052 second_actual = ROUND_TO_PAGE(hdr->second_size, page_mask);
1053 #ifdef TZ_SAVE_KERNEL_HASH
1054 aboot_save_boot_hash_mmc((uint32_t) image_addr, imagesize_actual);
1055 #endif /* TZ_SAVE_KERNEL_HASH */
Amit Blay4aa292f2015-04-28 21:55:59 +03001056
1057#ifdef MDTP_SUPPORT
1058 {
1059 /* Verify MDTP lock.
1060 * For boot & recovery partitions, MDTP will use boot_verifier APIs,
1061 * since verification was skipped in aboot. The signature is not part of the loaded image.
1062 */
1063 mdtp_ext_partition_verification_t ext_partition;
1064 ext_partition.partition = boot_into_recovery ? MDTP_PARTITION_RECOVERY : MDTP_PARTITION_BOOT;
1065 ext_partition.integrity_state = MDTP_PARTITION_STATE_UNSET;
1066 ext_partition.page_size = page_size;
1067 ext_partition.image_addr = (uint32)image_addr;
1068 ext_partition.image_size = imagesize_actual;
1069 ext_partition.sig_avail = FALSE;
1070 mdtp_fwlock_verify_lock(&ext_partition);
1071 }
1072#endif /* MDTP_SUPPORT */
Abhimanyu Kapur0f79d572014-02-19 22:03:02 -08001073 }
1074
Channagoud Kadabia22144f2013-03-20 11:49:01 -07001075 /*
Matthew Qinbb7923d2015-02-09 10:56:09 +08001076 * Check if the kernel image is a gzip package. If yes, need to decompress it.
1077 * If not, continue booting.
1078 */
1079 if (is_gzip_package((unsigned char *)(image_addr + page_size), hdr->kernel_size))
1080 {
1081 out_addr = (unsigned char *)(image_addr + imagesize_actual + page_size);
1082 out_avai_len = target_get_max_flash_size() - imagesize_actual - page_size;
Matthew Qin0b15b322015-05-19 05:20:54 -04001083 dprintf(INFO, "decompressing kernel image: start\n");
Matthew Qinbb7923d2015-02-09 10:56:09 +08001084 rc = decompress((unsigned char *)(image_addr + page_size),
1085 hdr->kernel_size, out_addr, out_avai_len,
1086 &dtb_offset, &out_len);
1087 if (rc)
1088 {
Matthew Qin0b15b322015-05-19 05:20:54 -04001089 dprintf(CRITICAL, "decompressing kernel image failed!!!\n");
Matthew Qinbb7923d2015-02-09 10:56:09 +08001090 ASSERT(0);
1091 }
1092
Matthew Qin0b15b322015-05-19 05:20:54 -04001093 dprintf(INFO, "decompressing kernel image: done\n");
Matthew Qinbb7923d2015-02-09 10:56:09 +08001094 kptr = (struct kernel64_hdr *)out_addr;
1095 kernel_start_addr = out_addr;
1096 kernel_size = out_len;
1097 } else {
1098 kptr = (struct kernel64_hdr *)(image_addr + page_size);
1099 kernel_start_addr = (unsigned char *)(image_addr + page_size);
1100 kernel_size = hdr->kernel_size;
1101 }
1102
1103 /*
Channagoud Kadabia22144f2013-03-20 11:49:01 -07001104 * Update the kernel/ramdisk/tags address if the boot image header
1105 * has default values, these default values come from mkbootimg when
1106 * the boot image is flashed using fastboot flash:raw
1107 */
Abhimanyu Kapur0f79d572014-02-19 22:03:02 -08001108 update_ker_tags_rdisk_addr(hdr, IS_ARM64(kptr));
Channagoud Kadabia22144f2013-03-20 11:49:01 -07001109
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001110 /* Get virtual addresses since the hdr saves physical addresses. */
1111 hdr->kernel_addr = VA((addr_t)(hdr->kernel_addr));
1112 hdr->ramdisk_addr = VA((addr_t)(hdr->ramdisk_addr));
1113 hdr->tags_addr = VA((addr_t)(hdr->tags_addr));
Deepa Dinamani0e163a42013-05-24 17:08:15 -07001114
Matthew Qinbb7923d2015-02-09 10:56:09 +08001115 kernel_size = ROUND_TO_PAGE(kernel_size, page_mask);
Deepa Dinamani0e163a42013-05-24 17:08:15 -07001116 /* Check if the addresses in the header are valid. */
Matthew Qinbb7923d2015-02-09 10:56:09 +08001117 if (check_aboot_addr_range_overlap(hdr->kernel_addr, kernel_size) ||
Deepa Dinamani0e163a42013-05-24 17:08:15 -07001118 check_aboot_addr_range_overlap(hdr->ramdisk_addr, ramdisk_actual))
1119 {
1120 dprintf(CRITICAL, "kernel/ramdisk addresses overlap with aboot addresses.\n");
1121 return -1;
1122 }
1123
1124#ifndef DEVICE_TREE
1125 if (check_aboot_addr_range_overlap(hdr->tags_addr, MAX_TAGS_SIZE))
1126 {
1127 dprintf(CRITICAL, "Tags addresses overlap with aboot addresses.\n");
1128 return -1;
1129 }
1130#endif
1131
Matthew Qin49e51fa2015-02-09 10:40:45 +08001132 /* Move kernel, ramdisk and device tree to correct address */
Matthew Qinbb7923d2015-02-09 10:56:09 +08001133 memmove((void*) hdr->kernel_addr, kernel_start_addr, kernel_size);
Matthew Qin49e51fa2015-02-09 10:40:45 +08001134 memmove((void*) hdr->ramdisk_addr, (char *)(image_addr + page_size + kernel_actual), hdr->ramdisk_size);
Shashank Mittald3e54dd2014-08-28 15:24:02 -07001135
Matthew Qin49e51fa2015-02-09 10:40:45 +08001136 #if DEVICE_TREE
1137 if(hdr->dt_size) {
1138 dt_table_offset = ((uint32_t)image_addr + page_size + kernel_actual + ramdisk_actual + second_actual);
1139 table = (struct dt_table*) dt_table_offset;
Deepa Dinamani0e163a42013-05-24 17:08:15 -07001140
Matthew Qin49e51fa2015-02-09 10:40:45 +08001141 if (dev_tree_validate(table, hdr->page_size, &dt_hdr_size) != 0) {
1142 dprintf(CRITICAL, "ERROR: Cannot validate Device Tree Table \n");
1143 return -1;
1144 }
Deepa Dinamani0e163a42013-05-24 17:08:15 -07001145
Matthew Qin49e51fa2015-02-09 10:40:45 +08001146 /* Find index of device tree within device tree table */
1147 if(dev_tree_get_entry_info(table, &dt_entry) != 0){
1148 dprintf(CRITICAL, "ERROR: Getting device tree address failed\n");
1149 return -1;
1150 }
Deepa Dinamani0e163a42013-05-24 17:08:15 -07001151
Matthew Qin271927e2015-03-31 22:07:07 -04001152 if (is_gzip_package((unsigned char *)dt_table_offset + dt_entry.offset, dt_entry.size))
1153 {
1154 unsigned int compressed_size = 0;
1155 out_addr += out_len;
1156 out_avai_len -= out_len;
Matthew Qin0b15b322015-05-19 05:20:54 -04001157 dprintf(INFO, "decompressing dtb: start\n");
Matthew Qin271927e2015-03-31 22:07:07 -04001158 rc = decompress((unsigned char *)dt_table_offset + dt_entry.offset,
1159 dt_entry.size, out_addr, out_avai_len,
1160 &compressed_size, &dtb_size);
1161 if (rc)
1162 {
Matthew Qin0b15b322015-05-19 05:20:54 -04001163 dprintf(CRITICAL, "decompressing dtb failed!!!\n");
Matthew Qin271927e2015-03-31 22:07:07 -04001164 ASSERT(0);
1165 }
1166
Matthew Qin0b15b322015-05-19 05:20:54 -04001167 dprintf(INFO, "decompressing dtb: done\n");
Matthew Qin271927e2015-03-31 22:07:07 -04001168 best_match_dt_addr = out_addr;
1169 } else {
1170 best_match_dt_addr = (unsigned char *)dt_table_offset + dt_entry.offset;
1171 dtb_size = dt_entry.size;
1172 }
1173
Matthew Qin49e51fa2015-02-09 10:40:45 +08001174 /* Validate and Read device device tree in the tags_addr */
Matthew Qin271927e2015-03-31 22:07:07 -04001175 if (check_aboot_addr_range_overlap(hdr->tags_addr, dtb_size))
Deepa Dinamani0e163a42013-05-24 17:08:15 -07001176 {
1177 dprintf(CRITICAL, "Device tree addresses overlap with aboot addresses.\n");
1178 return -1;
1179 }
Shashank Mittal162244e2011-08-08 19:01:25 -07001180
Matthew Qin271927e2015-03-31 22:07:07 -04001181 memmove((void *)hdr->tags_addr, (char *)best_match_dt_addr, dtb_size);
Matthew Qin49e51fa2015-02-09 10:40:45 +08001182 } else {
1183 /* Validate the tags_addr */
1184 if (check_aboot_addr_range_overlap(hdr->tags_addr, kernel_actual))
Channagoud Kadabi82cf5c62014-08-24 22:17:34 -07001185 {
1186 dprintf(CRITICAL, "Device tree addresses overlap with aboot addresses.\n");
1187 return -1;
1188 }
Matthew Qin49e51fa2015-02-09 10:40:45 +08001189 /*
1190 * If appended dev tree is found, update the atags with
1191 * memory address to the DTB appended location on RAM.
1192 * Else update with the atags address in the kernel header
1193 */
1194 void *dtb;
Matthew Qinbb7923d2015-02-09 10:56:09 +08001195 dtb = dev_tree_appended((void*)(image_addr + page_size),
1196 hdr->kernel_size, dtb_offset,
Matthew Qin49e51fa2015-02-09 10:40:45 +08001197 (void *)hdr->tags_addr);
1198 if (!dtb) {
1199 dprintf(CRITICAL, "ERROR: Appended Device Tree Blob not found\n");
Channagoud Kadabi82cf5c62014-08-24 22:17:34 -07001200 return -1;
1201 }
Shashank Mittalcd98d472011-08-02 14:29:24 -07001202 }
Matthew Qin49e51fa2015-02-09 10:40:45 +08001203 #endif
Shashank Mittal23b8f422010-04-16 19:27:21 -07001204
Stanimir Varbanov69ec5462013-07-18 18:17:42 +03001205 if (boot_into_recovery && !device.is_unlocked && !device.is_tampered)
1206 target_load_ssd_keystore();
1207
Shashank Mittal23b8f422010-04-16 19:27:21 -07001208unified_boot:
Shashank Mittal23b8f422010-04-16 19:27:21 -07001209
Dima Zavin77e41f32013-03-06 16:10:43 -08001210 boot_linux((void *)hdr->kernel_addr, (void *)hdr->tags_addr,
Dima Zavinbd3daa02013-03-26 11:06:44 -07001211 (const char *)hdr->cmdline, board_machtype(),
Shashank Mittal23b8f422010-04-16 19:27:21 -07001212 (void *)hdr->ramdisk_addr, hdr->ramdisk_size);
1213
1214 return 0;
1215}
1216
Dima Zavin214cc642009-01-26 11:16:21 -08001217int boot_linux_from_flash(void)
1218{
1219 struct boot_img_hdr *hdr = (void*) buf;
Dima Zavin214cc642009-01-26 11:16:21 -08001220 struct ptentry *ptn;
1221 struct ptable *ptable;
1222 unsigned offset = 0;
Chandan Uddarajude85d3f2010-01-05 16:32:33 -08001223
Shashank Mittalcd98d472011-08-02 14:29:24 -07001224 unsigned char *image_addr = 0;
1225 unsigned kernel_actual;
1226 unsigned ramdisk_actual;
1227 unsigned imagesize_actual;
Amol Jadib6be5c12012-11-14 13:39:51 -08001228 unsigned second_actual;
Shashank Mittalcd98d472011-08-02 14:29:24 -07001229
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -07001230#if DEVICE_TREE
1231 struct dt_table *table;
Joel Kingaa335dc2013-06-03 16:11:08 -07001232 struct dt_entry dt_entry;
Deepa Dinamani7aaf83d2012-12-21 11:27:01 -08001233 uint32_t dt_actual;
Deepa Dinamani19648b42013-09-05 17:05:55 -07001234 uint32_t dt_hdr_size;
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -07001235#endif
1236
David Ng183a7422009-12-07 14:55:21 -08001237 if (target_is_emmc_boot()) {
1238 hdr = (struct boot_img_hdr *)EMMC_BOOT_IMG_HEADER_ADDR;
1239 if (memcmp(hdr->magic, BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
1240 dprintf(CRITICAL, "ERROR: Invalid boot image header\n");
1241 return -1;
1242 }
1243 goto continue_boot;
1244 }
1245
Dima Zavin214cc642009-01-26 11:16:21 -08001246 ptable = flash_get_ptable();
1247 if (ptable == NULL) {
1248 dprintf(CRITICAL, "ERROR: Partition table not found\n");
1249 return -1;
1250 }
1251
Chandan Uddarajude85d3f2010-01-05 16:32:33 -08001252 if(!boot_into_recovery)
1253 {
1254 ptn = ptable_find(ptable, "boot");
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -07001255
Chandan Uddarajude85d3f2010-01-05 16:32:33 -08001256 if (ptn == NULL) {
1257 dprintf(CRITICAL, "ERROR: No boot partition found\n");
1258 return -1;
1259 }
1260 }
1261 else
1262 {
1263 ptn = ptable_find(ptable, "recovery");
1264 if (ptn == NULL) {
1265 dprintf(CRITICAL, "ERROR: No recovery partition found\n");
1266 return -1;
1267 }
Dima Zavin214cc642009-01-26 11:16:21 -08001268 }
1269
Shashank Mittaldcc2e352009-11-19 19:11:16 -08001270 if (flash_read(ptn, offset, buf, page_size)) {
Dima Zavin214cc642009-01-26 11:16:21 -08001271 dprintf(CRITICAL, "ERROR: Cannot read boot image header\n");
1272 return -1;
1273 }
Dima Zavin214cc642009-01-26 11:16:21 -08001274
1275 if (memcmp(hdr->magic, BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
Kinson Chik kchik@codeaurora.org82e4ae62011-04-12 17:42:07 -07001276 dprintf(CRITICAL, "ERROR: Invalid boot image header\n");
Dima Zavin214cc642009-01-26 11:16:21 -08001277 return -1;
1278 }
1279
Shashank Mittaldcc2e352009-11-19 19:11:16 -08001280 if (hdr->page_size != page_size) {
Kinson Chik kchik@codeaurora.org82e4ae62011-04-12 17:42:07 -07001281 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 -08001282 return -1;
1283 }
1284
Channagoud Kadabia22144f2013-03-20 11:49:01 -07001285 /*
1286 * Update the kernel/ramdisk/tags address if the boot image header
1287 * has default values, these default values come from mkbootimg when
1288 * the boot image is flashed using fastboot flash:raw
1289 */
Abhimanyu Kapur0f79d572014-02-19 22:03:02 -08001290 update_ker_tags_rdisk_addr(hdr, false);
Channagoud Kadabia22144f2013-03-20 11:49:01 -07001291
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001292 /* Get virtual addresses since the hdr saves physical addresses. */
Deepa Dinamani0e163a42013-05-24 17:08:15 -07001293 hdr->kernel_addr = VA((addr_t)(hdr->kernel_addr));
1294 hdr->ramdisk_addr = VA((addr_t)(hdr->ramdisk_addr));
1295 hdr->tags_addr = VA((addr_t)(hdr->tags_addr));
1296
1297 kernel_actual = ROUND_TO_PAGE(hdr->kernel_size, page_mask);
1298 ramdisk_actual = ROUND_TO_PAGE(hdr->ramdisk_size, page_mask);
1299
1300 /* Check if the addresses in the header are valid. */
1301 if (check_aboot_addr_range_overlap(hdr->kernel_addr, kernel_actual) ||
1302 check_aboot_addr_range_overlap(hdr->ramdisk_addr, ramdisk_actual))
1303 {
1304 dprintf(CRITICAL, "kernel/ramdisk addresses overlap with aboot addresses.\n");
1305 return -1;
1306 }
1307
1308#ifndef DEVICE_TREE
1309 if (check_aboot_addr_range_overlap(hdr->tags_addr, MAX_TAGS_SIZE))
1310 {
1311 dprintf(CRITICAL, "Tags addresses overlap with aboot addresses.\n");
1312 return -1;
1313 }
1314#endif
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001315
Shashank Mittalcd98d472011-08-02 14:29:24 -07001316 /* Authenticate Kernel */
Deepa Dinamani23b60d42013-06-24 18:10:52 -07001317 if(target_use_signed_kernel() && (!device.is_unlocked))
Shashank Mittalcd98d472011-08-02 14:29:24 -07001318 {
1319 image_addr = (unsigned char *)target_get_scratch_address();
Deepa Dinamani0e163a42013-05-24 17:08:15 -07001320 offset = 0;
1321
Deepa Dinamani7aaf83d2012-12-21 11:27:01 -08001322#if DEVICE_TREE
1323 dt_actual = ROUND_TO_PAGE(hdr->dt_size, page_mask);
1324 imagesize_actual = (page_size + kernel_actual + ramdisk_actual + dt_actual);
Deepa Dinamani0e163a42013-05-24 17:08:15 -07001325
1326 if (check_aboot_addr_range_overlap(hdr->tags_addr, hdr->dt_size))
1327 {
1328 dprintf(CRITICAL, "Device tree addresses overlap with aboot addresses.\n");
1329 return -1;
1330 }
Deepa Dinamani7aaf83d2012-12-21 11:27:01 -08001331#else
Shashank Mittalcd98d472011-08-02 14:29:24 -07001332 imagesize_actual = (page_size + kernel_actual + ramdisk_actual);
Deepa Dinamani7aaf83d2012-12-21 11:27:01 -08001333#endif
Shashank Mittal162244e2011-08-08 19:01:25 -07001334
Amol Jadib6be5c12012-11-14 13:39:51 -08001335 dprintf(INFO, "Loading boot image (%d): start\n", imagesize_actual);
Amol Jadi492d5a52013-03-15 16:12:34 -07001336 bs_set_timestamp(BS_KERNEL_LOAD_START);
Amol Jadib6be5c12012-11-14 13:39:51 -08001337
Shashank Mittalcd98d472011-08-02 14:29:24 -07001338 /* Read image without signature */
1339 if (flash_read(ptn, offset, (void *)image_addr, imagesize_actual))
1340 {
1341 dprintf(CRITICAL, "ERROR: Cannot read boot image\n");
1342 return -1;
1343 }
Dima Zavin214cc642009-01-26 11:16:21 -08001344
Amol Jadib6be5c12012-11-14 13:39:51 -08001345 dprintf(INFO, "Loading boot image (%d): done\n", imagesize_actual);
Amol Jadi492d5a52013-03-15 16:12:34 -07001346 bs_set_timestamp(BS_KERNEL_LOAD_DONE);
Amol Jadib6be5c12012-11-14 13:39:51 -08001347
Shashank Mittalcd98d472011-08-02 14:29:24 -07001348 offset = imagesize_actual;
1349 /* Read signature */
1350 if (flash_read(ptn, offset, (void *)(image_addr + offset), page_size))
1351 {
1352 dprintf(CRITICAL, "ERROR: Cannot read boot image signature\n");
Deepa Dinamani0e163a42013-05-24 17:08:15 -07001353 return -1;
Shashank Mittalcd98d472011-08-02 14:29:24 -07001354 }
Shashank Mittalcd98d472011-08-02 14:29:24 -07001355
Unnati Gandhi0c8e7c52014-07-17 14:33:09 +05301356 verify_signed_bootimg((uint32_t)image_addr, imagesize_actual);
Shashank Mittalcd98d472011-08-02 14:29:24 -07001357
1358 /* Move kernel and ramdisk to correct address */
Matthew Qinbb7923d2015-02-09 10:56:09 +08001359 memmove((void*) hdr->kernel_addr, (char*) (image_addr + page_size), hdr->kernel_size);
1360 memmove((void*) hdr->ramdisk_addr, (char*) (image_addr + page_size + kernel_actual), hdr->ramdisk_size);
Deepa Dinamani7aaf83d2012-12-21 11:27:01 -08001361#if DEVICE_TREE
Deepa Dinamani0e163a42013-05-24 17:08:15 -07001362 /* Validate and Read device device tree in the "tags_add */
Joel Kingaa335dc2013-06-03 16:11:08 -07001363 if (check_aboot_addr_range_overlap(hdr->tags_addr, dt_entry.size))
Deepa Dinamani0e163a42013-05-24 17:08:15 -07001364 {
1365 dprintf(CRITICAL, "Device tree addresses overlap with aboot addresses.\n");
1366 return -1;
1367 }
1368
Deepa Dinamani7aaf83d2012-12-21 11:27:01 -08001369 memmove((void*) hdr->tags_addr, (char *)(image_addr + page_size + kernel_actual + ramdisk_actual), hdr->dt_size);
1370#endif
Shashank Mittal162244e2011-08-08 19:01:25 -07001371
1372 /* Make sure everything from scratch address is read before next step!*/
Shashank Mittala0032282011-08-26 14:50:11 -07001373 if(device.is_tampered)
Shashank Mittal162244e2011-08-08 19:01:25 -07001374 {
1375 write_device_info_flash(&device);
1376 }
Channagoud Kadabi5c86fe32012-02-16 10:58:48 +05301377#if USE_PCOM_SECBOOT
1378 set_tamper_flag(device.is_tampered);
1379#endif
Shashank Mittalcd98d472011-08-02 14:29:24 -07001380 }
1381 else
1382 {
Shashank Mittal162244e2011-08-08 19:01:25 -07001383 offset = page_size;
1384
Amol Jadib6be5c12012-11-14 13:39:51 -08001385 kernel_actual = ROUND_TO_PAGE(hdr->kernel_size, page_mask);
1386 ramdisk_actual = ROUND_TO_PAGE(hdr->ramdisk_size, page_mask);
1387 second_actual = ROUND_TO_PAGE(hdr->second_size, page_mask);
1388
1389 dprintf(INFO, "Loading boot image (%d): start\n",
1390 kernel_actual + ramdisk_actual);
Amol Jadi492d5a52013-03-15 16:12:34 -07001391 bs_set_timestamp(BS_KERNEL_LOAD_START);
Amol Jadib6be5c12012-11-14 13:39:51 -08001392
1393 if (flash_read(ptn, offset, (void *)hdr->kernel_addr, kernel_actual)) {
Shashank Mittalcd98d472011-08-02 14:29:24 -07001394 dprintf(CRITICAL, "ERROR: Cannot read kernel image\n");
1395 return -1;
1396 }
Amol Jadib6be5c12012-11-14 13:39:51 -08001397 offset += kernel_actual;
Shashank Mittalcd98d472011-08-02 14:29:24 -07001398
Amol Jadib6be5c12012-11-14 13:39:51 -08001399 if (flash_read(ptn, offset, (void *)hdr->ramdisk_addr, ramdisk_actual)) {
Shashank Mittalcd98d472011-08-02 14:29:24 -07001400 dprintf(CRITICAL, "ERROR: Cannot read ramdisk image\n");
1401 return -1;
1402 }
Amol Jadib6be5c12012-11-14 13:39:51 -08001403 offset += ramdisk_actual;
1404
1405 dprintf(INFO, "Loading boot image (%d): done\n",
1406 kernel_actual + ramdisk_actual);
Amol Jadi492d5a52013-03-15 16:12:34 -07001407 bs_set_timestamp(BS_KERNEL_LOAD_DONE);
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -07001408
1409 if(hdr->second_size != 0) {
Amol Jadib6be5c12012-11-14 13:39:51 -08001410 offset += second_actual;
1411 /* Second image loading not implemented. */
1412 ASSERT(0);
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -07001413 }
1414
1415#if DEVICE_TREE
1416 if(hdr->dt_size != 0) {
1417
1418 /* Read the device tree table into buffer */
1419 if(flash_read(ptn, offset, (void *) dt_buf, page_size)) {
1420 dprintf(CRITICAL, "ERROR: Cannot read the Device Tree Table\n");
1421 return -1;
1422 }
1423
1424 table = (struct dt_table*) dt_buf;
1425
Deepa Dinamani19648b42013-09-05 17:05:55 -07001426 if (dev_tree_validate(table, hdr->page_size, &dt_hdr_size) != 0) {
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -07001427 dprintf(CRITICAL, "ERROR: Cannot validate Device Tree Table \n");
1428 return -1;
1429 }
1430
Deepa Dinamani19648b42013-09-05 17:05:55 -07001431 table = (struct dt_table*) memalign(CACHE_LINE, dt_hdr_size);
1432 if (!table)
1433 return -1;
1434
1435 /* Read the entire device tree table into buffer */
1436 if(flash_read(ptn, offset, (void *)table, dt_hdr_size)) {
1437 dprintf(CRITICAL, "ERROR: Cannot read the Device Tree Table\n");
1438 return -1;
1439 }
1440
1441
Joel Kingaa335dc2013-06-03 16:11:08 -07001442 /* Find index of device tree within device tree table */
1443 if(dev_tree_get_entry_info(table, &dt_entry) != 0){
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -07001444 dprintf(CRITICAL, "ERROR: Getting device tree address failed\n");
1445 return -1;
1446 }
1447
Deepa Dinamani0e163a42013-05-24 17:08:15 -07001448 /* Validate and Read device device tree in the "tags_add */
Joel Kingaa335dc2013-06-03 16:11:08 -07001449 if (check_aboot_addr_range_overlap(hdr->tags_addr, dt_entry.size))
Deepa Dinamani0e163a42013-05-24 17:08:15 -07001450 {
1451 dprintf(CRITICAL, "Device tree addresses overlap with aboot addresses.\n");
1452 return -1;
1453 }
1454
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -07001455 /* Read device device tree in the "tags_add */
Joel Kingaa335dc2013-06-03 16:11:08 -07001456 if(flash_read(ptn, offset + dt_entry.offset,
1457 (void *)hdr->tags_addr, dt_entry.size)) {
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -07001458 dprintf(CRITICAL, "ERROR: Cannot read device tree\n");
1459 return -1;
1460 }
1461 }
1462#endif
1463
Shashank Mittalcd98d472011-08-02 14:29:24 -07001464 }
David Ng183a7422009-12-07 14:55:21 -08001465continue_boot:
Dima Zavin214cc642009-01-26 11:16:21 -08001466
Dima Zavin214cc642009-01-26 11:16:21 -08001467 /* TODO: create/pass atags to kernel */
1468
Ajay Dudanie28a6072011-07-01 13:59:46 -07001469 boot_linux((void *)hdr->kernel_addr, (void *)hdr->tags_addr,
Dima Zavinbd3daa02013-03-26 11:06:44 -07001470 (const char *)hdr->cmdline, board_machtype(),
Dima Zavin214cc642009-01-26 11:16:21 -08001471 (void *)hdr->ramdisk_addr, hdr->ramdisk_size);
1472
1473 return 0;
1474}
Brian Swetland9c4c0752009-01-25 16:23:50 -08001475
Shashank Mittal162244e2011-08-08 19:01:25 -07001476void write_device_info_mmc(device_info *dev)
1477{
Shashank Mittal162244e2011-08-08 19:01:25 -07001478 unsigned long long ptn = 0;
1479 unsigned long long size;
1480 int index = INVALID_PTN;
Channagoud Kadabi749b0f82013-09-10 22:36:02 -07001481 uint32_t blocksize;
Sundarajan Srinivasand3514bb2013-12-04 17:02:00 -08001482 uint8_t lun = 0;
Channagoud Kadabi80a182b2015-03-11 17:04:23 -07001483 uint32_t ret = 0;
Shashank Mittal162244e2011-08-08 19:01:25 -07001484
Channagoud Kadabi80a182b2015-03-11 17:04:23 -07001485 if (devinfo_present)
1486 index = partition_get_index("devinfo");
1487 else
1488 index = partition_get_index("aboot");
Channagoud Kadabi5d0371c2014-10-21 22:27:07 -07001489
Shashank Mittal162244e2011-08-08 19:01:25 -07001490 ptn = partition_get_offset(index);
1491 if(ptn == 0)
1492 {
1493 return;
1494 }
1495
Sundarajan Srinivasand3514bb2013-12-04 17:02:00 -08001496 lun = partition_get_lun(index);
1497 mmc_set_lun(lun);
1498
Shashank Mittal162244e2011-08-08 19:01:25 -07001499 size = partition_get_size(index);
1500
Channagoud Kadabi749b0f82013-09-10 22:36:02 -07001501 blocksize = mmc_get_device_blocksize();
1502
Channagoud Kadabi80a182b2015-03-11 17:04:23 -07001503 if (devinfo_present)
1504 ret = mmc_write(ptn, blocksize, (void *)info_buf);
1505 else
1506 ret = mmc_write((ptn + size - blocksize), blocksize, (void *)info_buf);
1507 if (ret)
Shashank Mittal162244e2011-08-08 19:01:25 -07001508 {
1509 dprintf(CRITICAL, "ERROR: Cannot write device info\n");
1510 return;
1511 }
1512}
1513
Channagoud Kadabi036c6052015-02-09 15:19:59 -08001514void read_device_info_mmc(struct device_info *info)
Shashank Mittal162244e2011-08-08 19:01:25 -07001515{
Shashank Mittal162244e2011-08-08 19:01:25 -07001516 unsigned long long ptn = 0;
1517 unsigned long long size;
1518 int index = INVALID_PTN;
Channagoud Kadabi749b0f82013-09-10 22:36:02 -07001519 uint32_t blocksize;
Channagoud Kadabi80a182b2015-03-11 17:04:23 -07001520 uint32_t ret = 0;
Shashank Mittal162244e2011-08-08 19:01:25 -07001521
Channagoud Kadabi80a182b2015-03-11 17:04:23 -07001522 if ((index = partition_get_index("devinfo")) < 0)
1523 {
1524 devinfo_present = false;
1525 index = partition_get_index("aboot");
1526 }
Channagoud Kadabi5d0371c2014-10-21 22:27:07 -07001527
Shashank Mittal162244e2011-08-08 19:01:25 -07001528 ptn = partition_get_offset(index);
1529 if(ptn == 0)
1530 {
1531 return;
1532 }
1533
Channagoud Kadabi5d0371c2014-10-21 22:27:07 -07001534 mmc_set_lun(partition_get_lun(index));
1535
Shashank Mittal162244e2011-08-08 19:01:25 -07001536 size = partition_get_size(index);
1537
Channagoud Kadabi749b0f82013-09-10 22:36:02 -07001538 blocksize = mmc_get_device_blocksize();
1539
Channagoud Kadabi80a182b2015-03-11 17:04:23 -07001540 if (devinfo_present)
1541 ret = mmc_read(ptn, (void *)info_buf, blocksize);
1542 else
1543 ret = mmc_read((ptn + size - blocksize), (void *)info_buf, blocksize);
1544 if (ret)
Shashank Mittal162244e2011-08-08 19:01:25 -07001545 {
1546 dprintf(CRITICAL, "ERROR: Cannot read device info\n");
1547 return;
1548 }
1549
Shashank Mittal162244e2011-08-08 19:01:25 -07001550}
1551
1552void write_device_info_flash(device_info *dev)
1553{
Sridhar Parasuram7e16d172015-07-05 11:35:23 -07001554 struct device_info *info = memalign(PAGE_SIZE, ROUNDUP(BOOT_IMG_MAX_PAGE_SIZE, PAGE_SIZE));
Shashank Mittal162244e2011-08-08 19:01:25 -07001555 struct ptentry *ptn;
1556 struct ptable *ptable;
Sridhar Parasuram7e16d172015-07-05 11:35:23 -07001557 if(info == NULL)
1558 {
1559 dprintf(CRITICAL, "Failed to allocate memory for device info struct\n");
1560 ASSERT(0);
1561 }
1562 info_buf = info;
Shashank Mittal162244e2011-08-08 19:01:25 -07001563 ptable = flash_get_ptable();
1564 if (ptable == NULL)
1565 {
1566 dprintf(CRITICAL, "ERROR: Partition table not found\n");
1567 return;
1568 }
1569
1570 ptn = ptable_find(ptable, "devinfo");
1571 if (ptn == NULL)
1572 {
Smita Ghosh670c8b82015-05-07 09:30:03 -07001573 dprintf(CRITICAL, "ERROR: No devinfo partition found\n");
Shashank Mittal162244e2011-08-08 19:01:25 -07001574 return;
1575 }
1576
1577 memcpy(info, dev, sizeof(device_info));
1578
1579 if (flash_write(ptn, 0, (void *)info_buf, page_size))
1580 {
1581 dprintf(CRITICAL, "ERROR: Cannot write device info\n");
1582 return;
1583 }
Sridhar Parasuram7e16d172015-07-05 11:35:23 -07001584 free(info);
Shashank Mittal162244e2011-08-08 19:01:25 -07001585}
1586
vijay kumarc65876c2015-04-24 13:29:16 +05301587static int read_allow_oem_unlock(device_info *dev)
1588{
1589 const char *ptn_name = "frp";
1590 unsigned offset;
1591 int index;
1592 unsigned long long ptn;
1593 unsigned long long ptn_size;
1594 unsigned blocksize = mmc_get_device_blocksize();
1595 char buf[blocksize];
1596
1597 index = partition_get_index(ptn_name);
1598 if (index == INVALID_PTN)
1599 {
1600 dprintf(CRITICAL, "No '%s' partition found\n", ptn_name);
1601 return -1;
1602 }
1603
1604 ptn = partition_get_offset(index);
1605 ptn_size = partition_get_size(index);
1606 offset = ptn_size - blocksize;
1607
1608 if (mmc_read(ptn + offset, (void *)buf, sizeof(buf)))
1609 {
1610 dprintf(CRITICAL, "Reading MMC failed\n");
1611 return -1;
1612 }
1613
1614 /*is_allow_unlock is a bool value stored at the LSB of last byte*/
1615 is_allow_unlock = buf[blocksize-1] & 0x01;
1616 return 0;
1617}
1618
1619static int write_allow_oem_unlock(bool allow_unlock)
1620{
1621 const char *ptn_name = "frp";
1622 unsigned offset;
1623
1624 int index;
1625 unsigned long long ptn;
1626 unsigned long long ptn_size;
1627 unsigned blocksize = mmc_get_device_blocksize();
1628 char buf[blocksize];
1629
1630 index = partition_get_index(ptn_name);
1631 if (index == INVALID_PTN)
1632 {
1633 dprintf(CRITICAL, "No '%s' partition found\n", ptn_name);
1634 return -1;
1635 }
1636
1637 ptn = partition_get_offset(index);
1638 ptn_size = partition_get_size(index);
1639 offset = ptn_size - blocksize;
1640
1641 if (mmc_read(ptn + offset, (void *)buf, sizeof(buf)))
1642 {
1643 dprintf(CRITICAL, "Reading MMC failed\n");
1644 return -1;
1645 }
1646
1647 /*is_allow_unlock is a bool value stored at the LSB of last byte*/
1648 buf[blocksize-1] = allow_unlock;
1649 if (mmc_write(ptn + offset, blocksize, buf))
1650 {
1651 dprintf(CRITICAL, "Writing MMC failed\n");
1652 return -1;
1653 }
1654
1655 return 0;
1656}
1657
Shashank Mittal162244e2011-08-08 19:01:25 -07001658void read_device_info_flash(device_info *dev)
1659{
Sridhar Parasuram7e16d172015-07-05 11:35:23 -07001660 struct device_info *info = memalign(PAGE_SIZE, ROUNDUP(BOOT_IMG_MAX_PAGE_SIZE, PAGE_SIZE));
Shashank Mittal162244e2011-08-08 19:01:25 -07001661 struct ptentry *ptn;
1662 struct ptable *ptable;
Sridhar Parasuram7e16d172015-07-05 11:35:23 -07001663 if(info == NULL)
1664 {
1665 dprintf(CRITICAL, "Failed to allocate memory for device info struct\n");
1666 ASSERT(0);
1667 }
1668 info_buf = info;
Shashank Mittal162244e2011-08-08 19:01:25 -07001669 ptable = flash_get_ptable();
1670 if (ptable == NULL)
1671 {
1672 dprintf(CRITICAL, "ERROR: Partition table not found\n");
1673 return;
1674 }
1675
1676 ptn = ptable_find(ptable, "devinfo");
1677 if (ptn == NULL)
1678 {
Smita Ghosh670c8b82015-05-07 09:30:03 -07001679 dprintf(CRITICAL, "ERROR: No devinfo partition found\n");
Shashank Mittal162244e2011-08-08 19:01:25 -07001680 return;
1681 }
1682
1683 if (flash_read(ptn, 0, (void *)info_buf, page_size))
1684 {
1685 dprintf(CRITICAL, "ERROR: Cannot write device info\n");
1686 return;
1687 }
1688
1689 if (memcmp(info->magic, DEVICE_MAGIC, DEVICE_MAGIC_SIZE))
1690 {
Shashank Mittal162244e2011-08-08 19:01:25 -07001691 memcpy(info->magic, DEVICE_MAGIC, DEVICE_MAGIC_SIZE);
1692 info->is_unlocked = 0;
Shashank Mittala0032282011-08-26 14:50:11 -07001693 info->is_tampered = 0;
Shashank Mittal162244e2011-08-08 19:01:25 -07001694 write_device_info_flash(info);
1695 }
1696 memcpy(dev, info, sizeof(device_info));
Sridhar Parasuram7e16d172015-07-05 11:35:23 -07001697 free(info);
Shashank Mittal162244e2011-08-08 19:01:25 -07001698}
1699
1700void write_device_info(device_info *dev)
1701{
1702 if(target_is_emmc_boot())
1703 {
Sridhar Parasuram7e16d172015-07-05 11:35:23 -07001704 struct device_info *info = memalign(PAGE_SIZE, ROUNDUP(BOOT_IMG_MAX_PAGE_SIZE, PAGE_SIZE));
1705 if(info == NULL)
1706 {
1707 dprintf(CRITICAL, "Failed to allocate memory for device info struct\n");
1708 ASSERT(0);
1709 }
1710 info_buf = info;
Channagoud Kadabi036c6052015-02-09 15:19:59 -08001711 memcpy(info, dev, sizeof(struct device_info));
1712
1713#if USE_RPMB_FOR_DEVINFO
1714 if (is_secure_boot_enable())
Sridhar Parasuram7e16d172015-07-05 11:35:23 -07001715 write_device_info_rpmb((void*) info, PAGE_SIZE);
Channagoud Kadabic80cb492015-04-28 16:08:28 -07001716 else
1717 write_device_info_mmc(info);
Channagoud Kadabi036c6052015-02-09 15:19:59 -08001718#else
1719 write_device_info_mmc(info);
1720#endif
Sridhar Parasuram7e16d172015-07-05 11:35:23 -07001721 free(info);
Shashank Mittal162244e2011-08-08 19:01:25 -07001722 }
1723 else
1724 {
1725 write_device_info_flash(dev);
1726 }
1727}
1728
1729void read_device_info(device_info *dev)
1730{
1731 if(target_is_emmc_boot())
1732 {
Sridhar Parasuram7e16d172015-07-05 11:35:23 -07001733 struct device_info *info = memalign(PAGE_SIZE, ROUNDUP(BOOT_IMG_MAX_PAGE_SIZE, PAGE_SIZE));
1734 if(info == NULL)
1735 {
1736 dprintf(CRITICAL, "Failed to allocate memory for device info struct\n");
1737 ASSERT(0);
1738 }
1739 info_buf = info;
Channagoud Kadabi036c6052015-02-09 15:19:59 -08001740
1741#if USE_RPMB_FOR_DEVINFO
1742 if (is_secure_boot_enable())
Sridhar Parasuram7e16d172015-07-05 11:35:23 -07001743 read_device_info_rpmb((void*) info, PAGE_SIZE);
Channagoud Kadabic80cb492015-04-28 16:08:28 -07001744 else
1745 read_device_info_mmc(info);
Channagoud Kadabi036c6052015-02-09 15:19:59 -08001746#else
1747 read_device_info_mmc(info);
1748#endif
1749
1750 if (memcmp(info->magic, DEVICE_MAGIC, DEVICE_MAGIC_SIZE))
1751 {
1752 memcpy(info->magic, DEVICE_MAGIC, DEVICE_MAGIC_SIZE);
Channagoud Kadabi05f78ba2015-07-06 11:58:14 -07001753 if (is_secure_boot_enable())
1754 info->is_unlocked = 0;
1755 else
Channagoud Kadabi2fda4092015-07-07 13:34:11 -07001756 info->is_unlocked = 1;
Channagoud Kadabi036c6052015-02-09 15:19:59 -08001757 info->is_tampered = 0;
Unnati Gandhia49daa12015-03-23 18:08:38 +05301758#if USER_BUILD_VARIANT
1759 info->charger_screen_enabled = 1;
1760#else
Channagoud Kadabi036c6052015-02-09 15:19:59 -08001761 info->charger_screen_enabled = 0;
Unnati Gandhia49daa12015-03-23 18:08:38 +05301762#endif
Channagoud Kadabi036c6052015-02-09 15:19:59 -08001763 write_device_info(info);
1764 }
1765 memcpy(dev, info, sizeof(device_info));
Sridhar Parasuram7e16d172015-07-05 11:35:23 -07001766 free(info);
Shashank Mittal162244e2011-08-08 19:01:25 -07001767 }
1768 else
1769 {
1770 read_device_info_flash(dev);
1771 }
1772}
1773
1774void reset_device_info()
1775{
1776 dprintf(ALWAYS, "reset_device_info called.");
Shashank Mittala0032282011-08-26 14:50:11 -07001777 device.is_tampered = 0;
Shashank Mittal162244e2011-08-08 19:01:25 -07001778 write_device_info(&device);
1779}
1780
1781void set_device_root()
1782{
1783 dprintf(ALWAYS, "set_device_root called.");
Shashank Mittala0032282011-08-26 14:50:11 -07001784 device.is_tampered = 1;
Shashank Mittal162244e2011-08-08 19:01:25 -07001785 write_device_info(&device);
1786}
1787
Amol Jadicb524072012-08-09 16:40:18 -07001788#if DEVICE_TREE
Matthew Qin271927e2015-03-31 22:07:07 -04001789int copy_dtb(uint8_t *boot_image_start, unsigned int scratch_offset)
Amol Jadicb524072012-08-09 16:40:18 -07001790{
1791 uint32 dt_image_offset = 0;
1792 uint32_t n;
1793 struct dt_table *table;
Joel Kingaa335dc2013-06-03 16:11:08 -07001794 struct dt_entry dt_entry;
Deepa Dinamani19648b42013-09-05 17:05:55 -07001795 uint32_t dt_hdr_size;
Matthew Qin271927e2015-03-31 22:07:07 -04001796 unsigned int compressed_size = 0;
1797 unsigned int dtb_size = 0;
1798 unsigned int out_avai_len = 0;
1799 unsigned char *out_addr = NULL;
1800 unsigned char *best_match_dt_addr = NULL;
1801 int rc;
Amol Jadicb524072012-08-09 16:40:18 -07001802
1803 struct boot_img_hdr *hdr = (struct boot_img_hdr *) (boot_image_start);
1804
Amol Jadicb524072012-08-09 16:40:18 -07001805 if(hdr->dt_size != 0) {
Amol Jadicb524072012-08-09 16:40:18 -07001806 /* add kernel offset */
1807 dt_image_offset += page_size;
1808 n = ROUND_TO_PAGE(hdr->kernel_size, page_mask);
1809 dt_image_offset += n;
1810
1811 /* add ramdisk offset */
1812 n = ROUND_TO_PAGE(hdr->ramdisk_size, page_mask);
1813 dt_image_offset += n;
1814
1815 /* add second offset */
1816 if(hdr->second_size != 0) {
1817 n = ROUND_TO_PAGE(hdr->second_size, page_mask);
1818 dt_image_offset += n;
1819 }
1820
1821 /* offset now point to start of dt.img */
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -07001822 table = (struct dt_table*)(boot_image_start + dt_image_offset);
Amol Jadicb524072012-08-09 16:40:18 -07001823
Deepa Dinamani19648b42013-09-05 17:05:55 -07001824 if (dev_tree_validate(table, hdr->page_size, &dt_hdr_size) != 0) {
Amol Jadicb524072012-08-09 16:40:18 -07001825 dprintf(CRITICAL, "ERROR: Cannot validate Device Tree Table \n");
1826 return -1;
1827 }
Joel Kingaa335dc2013-06-03 16:11:08 -07001828 /* Find index of device tree within device tree table */
1829 if(dev_tree_get_entry_info(table, &dt_entry) != 0){
Amol Jadicb524072012-08-09 16:40:18 -07001830 dprintf(CRITICAL, "ERROR: Getting device tree address failed\n");
1831 return -1;
1832 }
1833
Matthew Qin271927e2015-03-31 22:07:07 -04001834 best_match_dt_addr = (unsigned char *)boot_image_start + dt_image_offset + dt_entry.offset;
1835 if (is_gzip_package(best_match_dt_addr, dt_entry.size))
1836 {
1837 out_addr = (unsigned char *)target_get_scratch_address() + scratch_offset;
1838 out_avai_len = target_get_max_flash_size() - scratch_offset;
Matthew Qin0b15b322015-05-19 05:20:54 -04001839 dprintf(INFO, "decompressing dtb: start\n");
Matthew Qin271927e2015-03-31 22:07:07 -04001840 rc = decompress(best_match_dt_addr,
1841 dt_entry.size, out_addr, out_avai_len,
1842 &compressed_size, &dtb_size);
1843 if (rc)
1844 {
Matthew Qin0b15b322015-05-19 05:20:54 -04001845 dprintf(CRITICAL, "decompressing dtb failed!!!\n");
Matthew Qin271927e2015-03-31 22:07:07 -04001846 ASSERT(0);
1847 }
1848
Matthew Qin0b15b322015-05-19 05:20:54 -04001849 dprintf(INFO, "decompressing dtb: done\n");
Matthew Qin271927e2015-03-31 22:07:07 -04001850 best_match_dt_addr = out_addr;
1851 } else {
1852 dtb_size = dt_entry.size;
1853 }
Deepa Dinamani0e163a42013-05-24 17:08:15 -07001854 /* Validate and Read device device tree in the "tags_add */
Matthew Qin271927e2015-03-31 22:07:07 -04001855 if (check_aboot_addr_range_overlap(hdr->tags_addr, dtb_size))
Deepa Dinamani0e163a42013-05-24 17:08:15 -07001856 {
1857 dprintf(CRITICAL, "Device tree addresses overlap with aboot addresses.\n");
1858 return -1;
1859 }
1860
Amol Jadicb524072012-08-09 16:40:18 -07001861 /* Read device device tree in the "tags_add */
Matthew Qin271927e2015-03-31 22:07:07 -04001862 memmove((void*) hdr->tags_addr, (void *)best_match_dt_addr, dtb_size);
Channagoud Kadabi8e9020f2013-04-16 11:24:32 -07001863 } else
1864 return -1;
Amol Jadicb524072012-08-09 16:40:18 -07001865
1866 /* Everything looks fine. Return success. */
1867 return 0;
1868}
1869#endif
1870
Brian Swetland9c4c0752009-01-25 16:23:50 -08001871void cmd_boot(const char *arg, void *data, unsigned sz)
1872{
1873 unsigned kernel_actual;
1874 unsigned ramdisk_actual;
Channagoud Kadabifc3b31f2014-06-18 17:41:01 -07001875 uint32_t image_actual;
1876 uint32_t dt_actual = 0;
Channagoud Kadabi3d839012014-06-26 14:26:39 -07001877 uint32_t sig_actual = SIGNATURE_SIZE;
Matthew Qinbb7923d2015-02-09 10:56:09 +08001878 struct boot_img_hdr *hdr = NULL;
1879 struct kernel64_hdr *kptr = NULL;
Brian Swetland9c4c0752009-01-25 16:23:50 -08001880 char *ptr = ((char*) data);
Channagoud Kadabi8e9020f2013-04-16 11:24:32 -07001881 int ret = 0;
1882 uint8_t dtb_copied = 0;
Matthew Qinbb7923d2015-02-09 10:56:09 +08001883 unsigned int out_len = 0;
1884 unsigned int out_avai_len = 0;
1885 unsigned char *out_addr = NULL;
1886 uint32_t dtb_offset = 0;
1887 unsigned char *kernel_start_addr = NULL;
1888 unsigned int kernel_size = 0;
Matthew Qin271927e2015-03-31 22:07:07 -04001889 unsigned int scratch_offset = 0;
Matthew Qinbb7923d2015-02-09 10:56:09 +08001890
Shashank Mittald3e54dd2014-08-28 15:24:02 -07001891#if VERIFIED_BOOT
Channagoud Kadabi6d5375e2015-06-23 17:15:42 -07001892 if(target_build_variant_user() && !device.is_unlocked)
Shashank Mittald3e54dd2014-08-28 15:24:02 -07001893 {
1894 fastboot_fail("unlock device to use this command");
1895 return;
1896 }
1897#endif
1898
Brian Swetland9c4c0752009-01-25 16:23:50 -08001899 if (sz < sizeof(hdr)) {
1900 fastboot_fail("invalid bootimage header");
1901 return;
1902 }
1903
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001904 hdr = (struct boot_img_hdr *)data;
Brian Swetland9c4c0752009-01-25 16:23:50 -08001905
1906 /* ensure commandline is terminated */
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001907 hdr->cmdline[BOOT_ARGS_SIZE-1] = 0;
Brian Swetland9c4c0752009-01-25 16:23:50 -08001908
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001909 if(target_is_emmc_boot() && hdr->page_size) {
1910 page_size = hdr->page_size;
Subbaraman Narayanamurthyfbe13a02010-09-10 11:51:12 -07001911 page_mask = page_size - 1;
1912 }
1913
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001914 kernel_actual = ROUND_TO_PAGE(hdr->kernel_size, page_mask);
1915 ramdisk_actual = ROUND_TO_PAGE(hdr->ramdisk_size, page_mask);
Channagoud Kadabifc3b31f2014-06-18 17:41:01 -07001916#if DEVICE_TREE
1917 dt_actual = ROUND_TO_PAGE(hdr->dt_size, page_mask);
1918#endif
1919
1920 image_actual = ADD_OF(page_size, kernel_actual);
1921 image_actual = ADD_OF(image_actual, ramdisk_actual);
1922 image_actual = ADD_OF(image_actual, dt_actual);
1923
Channagoud Kadabi3d839012014-06-26 14:26:39 -07001924 if (target_use_signed_kernel() && (!device.is_unlocked))
1925 image_actual = ADD_OF(image_actual, sig_actual);
1926
Channagoud Kadabifc3b31f2014-06-18 17:41:01 -07001927 /* sz should have atleast raw boot image */
1928 if (image_actual > sz) {
Channagoud Kadabi3d839012014-06-26 14:26:39 -07001929 fastboot_fail("bootimage: incomplete or not signed");
Channagoud Kadabifc3b31f2014-06-18 17:41:01 -07001930 return;
1931 }
1932
1933 /* Verify the boot image
1934 * device & page_size are initialized in aboot_init
1935 */
1936 if (target_use_signed_kernel() && (!device.is_unlocked))
Channagoud Kadabi3d839012014-06-26 14:26:39 -07001937 /* Pass size excluding signature size, otherwise we would try to
1938 * access signature beyond its length
1939 */
1940 verify_signed_bootimg((uint32_t)data, (image_actual - sig_actual));
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001941
Amit Blay4aa292f2015-04-28 21:55:59 +03001942#ifdef MDTP_SUPPORT
1943 else
1944 {
Shay Nachmani062aa3f2015-05-17 17:28:44 +03001945 /* fastboot boot is not allowed when MDTP is activated */
1946
Amit Blay4aa292f2015-04-28 21:55:59 +03001947 mdtp_ext_partition_verification_t ext_partition;
1948 ext_partition.partition = boot_into_recovery ? MDTP_PARTITION_RECOVERY : MDTP_PARTITION_BOOT;
1949 ext_partition.integrity_state = MDTP_PARTITION_STATE_UNSET;
1950 ext_partition.page_size = page_size;
1951 ext_partition.image_addr = (uint32_t)data;
1952 ext_partition.image_size = image_actual - sig_actual;
1953 ext_partition.sig_avail = TRUE;
1954 mdtp_fwlock_verify_lock(&ext_partition);
1955 }
Shay Nachmani062aa3f2015-05-17 17:28:44 +03001956
1957 bool is_mdtp_activated = 0;
1958 mdtp_activated(&is_mdtp_activated);
1959 if(is_mdtp_activated){
1960 dprintf(CRITICAL, "fastboot boot command is not available.\n");
1961 return;
1962 }
Amit Blay4aa292f2015-04-28 21:55:59 +03001963#endif /* MDTP_SUPPORT */
1964
Channagoud Kadabia22144f2013-03-20 11:49:01 -07001965 /*
Matthew Qinbb7923d2015-02-09 10:56:09 +08001966 * Check if the kernel image is a gzip package. If yes, need to decompress it.
1967 * If not, continue booting.
1968 */
1969 if (is_gzip_package((unsigned char *)(data + page_size), hdr->kernel_size))
1970 {
1971 out_addr = (unsigned char *)target_get_scratch_address();
1972 out_addr = (unsigned char *)(out_addr + image_actual + page_size);
1973 out_avai_len = target_get_max_flash_size() - image_actual - page_size;
Matthew Qin0b15b322015-05-19 05:20:54 -04001974 dprintf(INFO, "decompressing kernel image: start\n");
Matthew Qinbb7923d2015-02-09 10:56:09 +08001975 ret = decompress((unsigned char *)(ptr + page_size),
1976 hdr->kernel_size, out_addr, out_avai_len,
1977 &dtb_offset, &out_len);
1978 if (ret)
1979 {
Matthew Qin0b15b322015-05-19 05:20:54 -04001980 dprintf(CRITICAL, "decompressing image failed!!!\n");
Matthew Qinbb7923d2015-02-09 10:56:09 +08001981 ASSERT(0);
1982 }
1983
Matthew Qin0b15b322015-05-19 05:20:54 -04001984 dprintf(INFO, "decompressing kernel image: done\n");
Matthew Qinbb7923d2015-02-09 10:56:09 +08001985 kptr = (struct kernel64_hdr *)out_addr;
1986 kernel_start_addr = out_addr;
1987 kernel_size = out_len;
1988 } else {
1989 kptr = (struct kernel64_hdr*)((char *)data + page_size);
1990 kernel_start_addr = (unsigned char *)((char *)data + page_size);
1991 kernel_size = hdr->kernel_size;
1992 }
1993
1994 /*
Channagoud Kadabia22144f2013-03-20 11:49:01 -07001995 * Update the kernel/ramdisk/tags address if the boot image header
1996 * has default values, these default values come from mkbootimg when
1997 * the boot image is flashed using fastboot flash:raw
1998 */
Abhimanyu Kapur0f79d572014-02-19 22:03:02 -08001999 update_ker_tags_rdisk_addr(hdr, IS_ARM64(kptr));
Dima Zavin3cadfff2013-03-21 14:30:48 -07002000
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07002001 /* Get virtual addresses since the hdr saves physical addresses. */
2002 hdr->kernel_addr = VA(hdr->kernel_addr);
2003 hdr->ramdisk_addr = VA(hdr->ramdisk_addr);
2004 hdr->tags_addr = VA(hdr->tags_addr);
Brian Swetland9c4c0752009-01-25 16:23:50 -08002005
Matthew Qinbb7923d2015-02-09 10:56:09 +08002006 kernel_size = ROUND_TO_PAGE(kernel_size, page_mask);
Deepa Dinamani0e163a42013-05-24 17:08:15 -07002007 /* Check if the addresses in the header are valid. */
Matthew Qinbb7923d2015-02-09 10:56:09 +08002008 if (check_aboot_addr_range_overlap(hdr->kernel_addr, kernel_size) ||
Deepa Dinamani0e163a42013-05-24 17:08:15 -07002009 check_aboot_addr_range_overlap(hdr->ramdisk_addr, ramdisk_actual))
2010 {
2011 dprintf(CRITICAL, "kernel/ramdisk addresses overlap with aboot addresses.\n");
Channagoud Kadabi881856c2013-12-03 11:19:20 -08002012 return;
Deepa Dinamani0e163a42013-05-24 17:08:15 -07002013 }
2014
Amol Jadicb524072012-08-09 16:40:18 -07002015#if DEVICE_TREE
Matthew Qin271927e2015-03-31 22:07:07 -04002016 scratch_offset = image_actual + page_size + out_len;
Amol Jadicb524072012-08-09 16:40:18 -07002017 /* find correct dtb and copy it to right location */
Matthew Qin271927e2015-03-31 22:07:07 -04002018 ret = copy_dtb(data, scratch_offset);
Channagoud Kadabi8e9020f2013-04-16 11:24:32 -07002019
2020 dtb_copied = !ret ? 1 : 0;
Deepa Dinamani0e163a42013-05-24 17:08:15 -07002021#else
2022 if (check_aboot_addr_range_overlap(hdr->tags_addr, MAX_TAGS_SIZE))
2023 {
2024 dprintf(CRITICAL, "Tags addresses overlap with aboot addresses.\n");
Channagoud Kadabi881856c2013-12-03 11:19:20 -08002025 return;
Deepa Dinamani0e163a42013-05-24 17:08:15 -07002026 }
Channagoud Kadabi8e9020f2013-04-16 11:24:32 -07002027#endif
2028
2029 /* Load ramdisk & kernel */
2030 memmove((void*) hdr->ramdisk_addr, ptr + page_size + kernel_actual, hdr->ramdisk_size);
Matthew Qinbb7923d2015-02-09 10:56:09 +08002031 memmove((void*) hdr->kernel_addr, (char*) (kernel_start_addr), kernel_size);
Channagoud Kadabi8e9020f2013-04-16 11:24:32 -07002032
2033#if DEVICE_TREE
Matthew Qinbb7923d2015-02-09 10:56:09 +08002034 if (check_aboot_addr_range_overlap(hdr->tags_addr, kernel_actual))
2035 {
2036 dprintf(CRITICAL, "Tags addresses overlap with aboot addresses.\n");
2037 return;
2038 }
2039
Channagoud Kadabi8e9020f2013-04-16 11:24:32 -07002040 /*
2041 * If dtb is not found look for appended DTB in the kernel.
2042 * If appended dev tree is found, update the atags with
2043 * memory address to the DTB appended location on RAM.
2044 * Else update with the atags address in the kernel header
2045 */
2046 if (!dtb_copied) {
2047 void *dtb;
Matthew Qinbb7923d2015-02-09 10:56:09 +08002048 dtb = dev_tree_appended((void*)(ptr + page_size),
2049 hdr->kernel_size, dtb_offset,
Dima Zavine63e5572013-05-03 12:23:06 -07002050 (void *)hdr->tags_addr);
Channagoud Kadabi8e9020f2013-04-16 11:24:32 -07002051 if (!dtb) {
2052 fastboot_fail("dtb not found");
2053 return;
2054 }
Amol Jadicb524072012-08-09 16:40:18 -07002055 }
2056#endif
Brian Swetland9c4c0752009-01-25 16:23:50 -08002057
2058 fastboot_okay("");
Amol Jadi7c4316c2013-10-07 14:19:26 -07002059 fastboot_stop();
Brian Swetland9c4c0752009-01-25 16:23:50 -08002060
Dima Zavin77e41f32013-03-06 16:10:43 -08002061 boot_linux((void*) hdr->kernel_addr, (void*) hdr->tags_addr,
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07002062 (const char*) hdr->cmdline, board_machtype(),
2063 (void*) hdr->ramdisk_addr, hdr->ramdisk_size);
Brian Swetland9c4c0752009-01-25 16:23:50 -08002064}
2065
Sridhar Parasurame94e8152014-10-24 14:06:03 -07002066void cmd_erase_nand(const char *arg, void *data, unsigned sz)
Dima Zavin214cc642009-01-26 11:16:21 -08002067{
2068 struct ptentry *ptn;
2069 struct ptable *ptable;
2070
2071 ptable = flash_get_ptable();
2072 if (ptable == NULL) {
2073 fastboot_fail("partition table doesn't exist");
2074 return;
2075 }
2076
2077 ptn = ptable_find(ptable, arg);
2078 if (ptn == NULL) {
2079 fastboot_fail("unknown partition name");
2080 return;
2081 }
2082
2083 if (flash_erase(ptn)) {
2084 fastboot_fail("failed to erase partition");
2085 return;
2086 }
2087 fastboot_okay("");
2088}
2089
Bikas Gurungd48bd242010-09-04 19:54:32 -07002090
2091void cmd_erase_mmc(const char *arg, void *data, unsigned sz)
2092{
2093 unsigned long long ptn = 0;
Oliver Wangcee448d2013-10-22 18:40:13 +08002094 unsigned long long size = 0;
Kinson Chikf1a43512011-07-14 11:28:39 -07002095 int index = INVALID_PTN;
Sundarajan Srinivasand3514bb2013-12-04 17:02:00 -08002096 uint8_t lun = 0;
Bikas Gurungd48bd242010-09-04 19:54:32 -07002097
Shashank Mittald3e54dd2014-08-28 15:24:02 -07002098#if VERIFIED_BOOT
2099 if(!strcmp(arg, KEYSTORE_PTN_NAME))
2100 {
2101 if(!device.is_unlocked)
2102 {
2103 fastboot_fail("unlock device to erase keystore");
2104 return;
2105 }
2106 }
2107#endif
2108
Kinson Chikf1a43512011-07-14 11:28:39 -07002109 index = partition_get_index(arg);
2110 ptn = partition_get_offset(index);
Oliver Wangcee448d2013-10-22 18:40:13 +08002111 size = partition_get_size(index);
Neeti Desaica8c9602011-10-06 11:40:00 -07002112
Kinson Chikf1a43512011-07-14 11:28:39 -07002113 if(ptn == 0) {
Neeti Desaica8c9602011-10-06 11:40:00 -07002114 fastboot_fail("Partition table doesn't exist\n");
Bikas Gurungd48bd242010-09-04 19:54:32 -07002115 return;
2116 }
Kun Liang2f1601a2013-08-12 16:29:54 +08002117
Sundarajan Srinivasand3514bb2013-12-04 17:02:00 -08002118 lun = partition_get_lun(index);
2119 mmc_set_lun(lun);
2120
Sridhar Parasuramd7957122015-02-27 11:33:40 -08002121 if (platform_boot_dev_isemmc())
2122 {
2123 if (mmc_erase_card(ptn, size)) {
2124 fastboot_fail("failed to erase partition\n");
2125 return;
2126 }
2127 } else {
2128 BUF_DMA_ALIGN(out, DEFAULT_ERASE_SIZE);
2129 size = partition_get_size(index);
2130 if (size > DEFAULT_ERASE_SIZE)
2131 size = DEFAULT_ERASE_SIZE;
Kun Liang2f1601a2013-08-12 16:29:54 +08002132
Sridhar Parasuramd7957122015-02-27 11:33:40 -08002133 /* Simple inefficient version of erase. Just writing
2134 0 in first several blocks */
2135 if (mmc_write(ptn , size, (unsigned int *)out)) {
2136 fastboot_fail("failed to erase partition");
2137 return;
2138 }
Bikas Gurungd48bd242010-09-04 19:54:32 -07002139 }
2140 fastboot_okay("");
2141}
2142
Sridhar Parasurame94e8152014-10-24 14:06:03 -07002143void cmd_erase(const char *arg, void *data, unsigned sz)
2144{
Channagoud Kadabice3cf422015-04-17 16:02:30 -07002145#if VERIFIED_BOOT
Channagoud Kadabi35297672015-06-13 11:09:49 -07002146 if (target_build_variant_user())
Channagoud Kadabice3cf422015-04-17 16:02:30 -07002147 {
Channagoud Kadabi35297672015-06-13 11:09:49 -07002148 if(!device.is_unlocked && !device.is_verified)
Channagoud Kadabice3cf422015-04-17 16:02:30 -07002149 {
Channagoud Kadabi35297672015-06-13 11:09:49 -07002150 fastboot_fail("device is locked. Cannot erase");
Channagoud Kadabice3cf422015-04-17 16:02:30 -07002151 return;
2152 }
Channagoud Kadabi35297672015-06-13 11:09:49 -07002153 if(!device.is_unlocked && device.is_verified)
2154 {
2155 if(!boot_verify_flash_allowed(arg))
2156 {
2157 fastboot_fail("cannot flash this partition in verified state");
2158 return;
2159 }
2160 }
Channagoud Kadabice3cf422015-04-17 16:02:30 -07002161 }
2162#endif
2163
Sridhar Parasurame94e8152014-10-24 14:06:03 -07002164 if(target_is_emmc_boot())
2165 cmd_erase_mmc(arg, data, sz);
2166 else
2167 cmd_erase_nand(arg, data, sz);
2168}
Bikas Gurungd48bd242010-09-04 19:54:32 -07002169
Ajay Dudani5c761132011-04-07 20:19:04 -07002170void cmd_flash_mmc_img(const char *arg, void *data, unsigned sz)
Shashank Mittal23b8f422010-04-16 19:27:21 -07002171{
2172 unsigned long long ptn = 0;
Subbaraman Narayanamurthyc95b5b12010-08-31 13:19:48 -07002173 unsigned long long size = 0;
Kinson Chikf1a43512011-07-14 11:28:39 -07002174 int index = INVALID_PTN;
Sundarajan Srinivasand3514bb2013-12-04 17:02:00 -08002175 char *token = NULL;
2176 char *pname = NULL;
Sridhar Parasuramefc133f2015-05-04 13:35:41 -07002177 char *sp;
Sundarajan Srinivasand3514bb2013-12-04 17:02:00 -08002178 uint8_t lun = 0;
2179 bool lun_set = false;
Subbaraman Narayanamurthyc95b5b12010-08-31 13:19:48 -07002180
Sridhar Parasuramefc133f2015-05-04 13:35:41 -07002181 token = strtok_r((char *)arg, ":", &sp);
Sundarajan Srinivasand3514bb2013-12-04 17:02:00 -08002182 pname = token;
Sridhar Parasuramefc133f2015-05-04 13:35:41 -07002183 token = strtok_r(NULL, ":", &sp);
Sundarajan Srinivasand3514bb2013-12-04 17:02:00 -08002184 if(token)
2185 {
2186 lun = atoi(token);
2187 mmc_set_lun(lun);
2188 lun_set = true;
2189 }
2190
Mao Jinlong226f33a2014-07-04 17:24:10 +08002191 if (pname)
Greg Grisco6e754772011-06-23 12:19:39 -07002192 {
Mao Jinlong226f33a2014-07-04 17:24:10 +08002193 if (!strcmp(pname, "partition"))
2194 {
2195 dprintf(INFO, "Attempt to write partition image.\n");
2196 if (write_partition(sz, (unsigned char *) data)) {
2197 fastboot_fail("failed to write partition");
Greg Grisco6e754772011-06-23 12:19:39 -07002198 return;
2199 }
2200 }
Mao Jinlong226f33a2014-07-04 17:24:10 +08002201 else
Sundarajan Srinivasand3514bb2013-12-04 17:02:00 -08002202 {
Shashank Mittald3e54dd2014-08-28 15:24:02 -07002203#if VERIFIED_BOOT
2204 if(!strcmp(pname, KEYSTORE_PTN_NAME))
2205 {
2206 if(!device.is_unlocked)
2207 {
2208 fastboot_fail("unlock device to flash keystore");
2209 return;
2210 }
2211 if(!boot_verify_validate_keystore((unsigned char *)data))
2212 {
2213 fastboot_fail("image is not a keystore file");
2214 return;
2215 }
2216 }
2217#endif
Mao Jinlong226f33a2014-07-04 17:24:10 +08002218 index = partition_get_index(pname);
2219 ptn = partition_get_offset(index);
2220 if(ptn == 0) {
2221 fastboot_fail("partition table doesn't exist");
2222 return;
2223 }
Sundarajan Srinivasand3514bb2013-12-04 17:02:00 -08002224
Mao Jinlong226f33a2014-07-04 17:24:10 +08002225 if (!strcmp(pname, "boot") || !strcmp(pname, "recovery")) {
2226 if (memcmp((void *)data, BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
2227 fastboot_fail("image is not a boot image");
2228 return;
2229 }
2230 }
2231
2232 if(!lun_set)
2233 {
2234 lun = partition_get_lun(index);
2235 mmc_set_lun(lun);
2236 }
2237
2238 size = partition_get_size(index);
2239 if (ROUND_TO_PAGE(sz,511) > size) {
2240 fastboot_fail("size too large");
2241 return;
2242 }
2243 else if (mmc_write(ptn , sz, (unsigned int *)data)) {
2244 fastboot_fail("flash write failure");
2245 return;
2246 }
Greg Grisco6e754772011-06-23 12:19:39 -07002247 }
Shashank Mittal23b8f422010-04-16 19:27:21 -07002248 }
2249 fastboot_okay("");
2250 return;
2251}
2252
Ajay Dudanide984792015-03-02 09:57:41 -08002253void cmd_flash_meta_img(const char *arg, void *data, unsigned sz)
2254{
2255 int i, images;
2256 meta_header_t *meta_header;
2257 img_header_entry_t *img_header_entry;
2258
2259 meta_header = (meta_header_t*) data;
2260 img_header_entry = (img_header_entry_t*) (data+sizeof(meta_header_t));
2261
2262 images = meta_header->img_hdr_sz / sizeof(img_header_entry_t);
2263
2264 for (i=0; i<images; i++) {
2265
2266 if((img_header_entry[i].ptn_name == NULL) ||
2267 (img_header_entry[i].start_offset == 0) ||
2268 (img_header_entry[i].size == 0))
2269 break;
2270
2271 cmd_flash_mmc_img(img_header_entry[i].ptn_name,
2272 (void *) data + img_header_entry[i].start_offset,
2273 img_header_entry[i].size);
2274 }
2275
Channagoud Kadabiaafbbfc2015-03-04 17:52:56 -08002276 if (!strncmp(arg, "bootloader", strlen("bootloader")))
2277 {
2278 strlcpy(device.bootloader_version, TARGET(BOARD), MAX_VERSION_LEN);
2279 strlcat(device.bootloader_version, "-", MAX_VERSION_LEN);
2280 strlcat(device.bootloader_version, meta_header->img_version, MAX_VERSION_LEN);
2281 }
2282 else
2283 {
2284 strlcpy(device.radio_version, TARGET(BOARD), MAX_VERSION_LEN);
2285 strlcat(device.radio_version, "-", MAX_VERSION_LEN);
2286 strlcat(device.radio_version, meta_header->img_version, MAX_VERSION_LEN);
2287 }
2288
2289 write_device_info(&device);
Ajay Dudanide984792015-03-02 09:57:41 -08002290 fastboot_okay("");
2291 return;
2292}
2293
Ajay Dudani5c761132011-04-07 20:19:04 -07002294void cmd_flash_mmc_sparse_img(const char *arg, void *data, unsigned sz)
2295{
2296 unsigned int chunk;
wufeng.jiang813dc352015-06-02 23:02:46 -04002297 uint64_t chunk_data_sz;
Channagoud Kadabif627cf82013-09-09 14:08:20 -07002298 uint32_t *fill_buf = NULL;
2299 uint32_t fill_val;
Ajay Dudani5c761132011-04-07 20:19:04 -07002300 sparse_header_t *sparse_header;
2301 chunk_header_t *chunk_header;
Ajay Dudaniab18f022011-05-12 14:39:22 -07002302 uint32_t total_blocks = 0;
Ajay Dudani5c761132011-04-07 20:19:04 -07002303 unsigned long long ptn = 0;
Channagoud Kadabi65b91002011-10-11 17:34:33 +05302304 unsigned long long size = 0;
Kinson Chikf1a43512011-07-14 11:28:39 -07002305 int index = INVALID_PTN;
Unnati Gandhi0c8e7c52014-07-17 14:33:09 +05302306 uint32_t i;
Sundarajan Srinivasand3514bb2013-12-04 17:02:00 -08002307 uint8_t lun = 0;
vijay kumar800255e2015-04-24 20:26:19 +05302308 /*End of the sparse image address*/
2309 uint32_t data_end = (uint32_t)data + sz;
Ajay Dudani5c761132011-04-07 20:19:04 -07002310
Kinson Chikf1a43512011-07-14 11:28:39 -07002311 index = partition_get_index(arg);
2312 ptn = partition_get_offset(index);
2313 if(ptn == 0) {
Ajay Dudani5c761132011-04-07 20:19:04 -07002314 fastboot_fail("partition table doesn't exist");
2315 return;
2316 }
2317
Channagoud Kadabi65b91002011-10-11 17:34:33 +05302318 size = partition_get_size(index);
Channagoud Kadabi65b91002011-10-11 17:34:33 +05302319
Sundarajan Srinivasand3514bb2013-12-04 17:02:00 -08002320 lun = partition_get_lun(index);
2321 mmc_set_lun(lun);
2322
vijay kumar800255e2015-04-24 20:26:19 +05302323 if (sz < sizeof(sparse_header_t)) {
2324 fastboot_fail("size too low");
2325 return;
2326 }
2327
Ajay Dudani5c761132011-04-07 20:19:04 -07002328 /* Read and skip over sparse image header */
2329 sparse_header = (sparse_header_t *) data;
vijay kumar800255e2015-04-24 20:26:19 +05302330
vijay kumar1321f342015-03-27 12:13:42 +05302331 if (((uint64_t)sparse_header->total_blks * (uint64_t)sparse_header->blk_sz) > size) {
Ajay Dudani876b3282012-12-21 14:12:17 -08002332 fastboot_fail("size too large");
2333 return;
2334 }
2335
vijay kumarde4fcf62015-04-23 13:05:49 +05302336 data += sizeof(sparse_header_t);
vijay kumar800255e2015-04-24 20:26:19 +05302337
2338 if (data_end < (uint32_t)data) {
2339 fastboot_fail("buffer overreads occured due to invalid sparse header");
2340 return;
2341 }
2342
vijay kumarde4fcf62015-04-23 13:05:49 +05302343 if(sparse_header->file_hdr_sz != sizeof(sparse_header_t))
Ajay Dudani5c761132011-04-07 20:19:04 -07002344 {
vijay kumarde4fcf62015-04-23 13:05:49 +05302345 fastboot_fail("sparse header size mismatch");
2346 return;
Ajay Dudani5c761132011-04-07 20:19:04 -07002347 }
2348
Ajay Dudanib06c05f2011-05-12 14:46:10 -07002349 dprintf (SPEW, "=== Sparse Image Header ===\n");
2350 dprintf (SPEW, "magic: 0x%x\n", sparse_header->magic);
2351 dprintf (SPEW, "major_version: 0x%x\n", sparse_header->major_version);
2352 dprintf (SPEW, "minor_version: 0x%x\n", sparse_header->minor_version);
2353 dprintf (SPEW, "file_hdr_sz: %d\n", sparse_header->file_hdr_sz);
2354 dprintf (SPEW, "chunk_hdr_sz: %d\n", sparse_header->chunk_hdr_sz);
2355 dprintf (SPEW, "blk_sz: %d\n", sparse_header->blk_sz);
2356 dprintf (SPEW, "total_blks: %d\n", sparse_header->total_blks);
2357 dprintf (SPEW, "total_chunks: %d\n", sparse_header->total_chunks);
Ajay Dudani5c761132011-04-07 20:19:04 -07002358
2359 /* Start processing chunks */
2360 for (chunk=0; chunk<sparse_header->total_chunks; chunk++)
2361 {
Aparna Mallavarapu2ae741a2015-03-28 01:41:08 +05302362 /* Make sure the total image size does not exceed the partition size */
2363 if(((uint64_t)total_blocks * (uint64_t)sparse_header->blk_sz) >= size) {
2364 fastboot_fail("size too large");
2365 return;
2366 }
Ajay Dudani5c761132011-04-07 20:19:04 -07002367 /* Read and skip over chunk header */
2368 chunk_header = (chunk_header_t *) data;
2369 data += sizeof(chunk_header_t);
2370
vijay kumar800255e2015-04-24 20:26:19 +05302371 if (data_end < (uint32_t)data) {
2372 fastboot_fail("buffer overreads occured due to invalid sparse header");
2373 return;
2374 }
2375
Ajay Dudani5c761132011-04-07 20:19:04 -07002376 dprintf (SPEW, "=== Chunk Header ===\n");
2377 dprintf (SPEW, "chunk_type: 0x%x\n", chunk_header->chunk_type);
2378 dprintf (SPEW, "chunk_data_sz: 0x%x\n", chunk_header->chunk_sz);
2379 dprintf (SPEW, "total_size: 0x%x\n", chunk_header->total_sz);
2380
vijay kumar800255e2015-04-24 20:26:19 +05302381 if(sparse_header->chunk_hdr_sz != sizeof(chunk_header_t))
Ajay Dudani5c761132011-04-07 20:19:04 -07002382 {
vijay kumar800255e2015-04-24 20:26:19 +05302383 fastboot_fail("chunk header size mismatch");
2384 return;
Ajay Dudani5c761132011-04-07 20:19:04 -07002385 }
2386
wufeng.jiang813dc352015-06-02 23:02:46 -04002387 if (!sparse_header->blk_sz ){
2388 fastboot_fail("Invalid block size\n");
Aparna Mallavarapu2ae741a2015-03-28 01:41:08 +05302389 return;
2390 }
2391
wufeng.jiang813dc352015-06-02 23:02:46 -04002392 chunk_data_sz = (uint64_t)sparse_header->blk_sz * chunk_header->chunk_sz;
2393
Aparna Mallavarapu2ae741a2015-03-28 01:41:08 +05302394 /* Make sure that the chunk size calculated from sparse image does not
2395 * exceed partition size
2396 */
2397 if ((uint64_t)total_blocks * (uint64_t)sparse_header->blk_sz + chunk_data_sz > size)
2398 {
2399 fastboot_fail("Chunk data size exceeds partition size");
2400 return;
2401 }
2402
Ajay Dudani5c761132011-04-07 20:19:04 -07002403 switch (chunk_header->chunk_type)
2404 {
2405 case CHUNK_TYPE_RAW:
wufeng.jiang813dc352015-06-02 23:02:46 -04002406 if((uint64_t)chunk_header->total_sz != ((uint64_t)sparse_header->chunk_hdr_sz +
Ajay Dudani5c761132011-04-07 20:19:04 -07002407 chunk_data_sz))
2408 {
2409 fastboot_fail("Bogus chunk size for chunk type Raw");
2410 return;
2411 }
2412
vijay kumar800255e2015-04-24 20:26:19 +05302413 if (data_end < (uint32_t)data + chunk_data_sz) {
2414 fastboot_fail("buffer overreads occured due to invalid sparse header");
2415 return;
2416 }
2417
wufeng.jiang813dc352015-06-02 23:02:46 -04002418 /* chunk_header->total_sz is uint32,So chunk_data_sz is now less than 2^32
2419 otherwise it will return in the line above
2420 */
Ajay Dudaniab18f022011-05-12 14:39:22 -07002421 if(mmc_write(ptn + ((uint64_t)total_blocks*sparse_header->blk_sz),
wufeng.jiang813dc352015-06-02 23:02:46 -04002422 (uint32_t)chunk_data_sz,
Ajay Dudaniab18f022011-05-12 14:39:22 -07002423 (unsigned int*)data))
Ajay Dudani5c761132011-04-07 20:19:04 -07002424 {
2425 fastboot_fail("flash write failure");
2426 return;
2427 }
Aparna Mallavarapu2ae741a2015-03-28 01:41:08 +05302428 if(total_blocks > (UINT_MAX - chunk_header->chunk_sz)) {
2429 fastboot_fail("Bogus size for RAW chunk type");
2430 return;
2431 }
Ajay Dudani5c761132011-04-07 20:19:04 -07002432 total_blocks += chunk_header->chunk_sz;
wufeng.jiang813dc352015-06-02 23:02:46 -04002433 data += (uint32_t)chunk_data_sz;
Ajay Dudani5c761132011-04-07 20:19:04 -07002434 break;
2435
Channagoud Kadabif627cf82013-09-09 14:08:20 -07002436 case CHUNK_TYPE_FILL:
2437 if(chunk_header->total_sz != (sparse_header->chunk_hdr_sz +
2438 sizeof(uint32_t)))
2439 {
2440 fastboot_fail("Bogus chunk size for chunk type FILL");
2441 return;
2442 }
2443
2444 fill_buf = (uint32_t *)memalign(CACHE_LINE, ROUNDUP(sparse_header->blk_sz, CACHE_LINE));
2445 if (!fill_buf)
2446 {
2447 fastboot_fail("Malloc failed for: CHUNK_TYPE_FILL");
2448 return;
2449 }
2450
vijay kumar800255e2015-04-24 20:26:19 +05302451 if (data_end < (uint32_t)data + sizeof(uint32_t)) {
2452 fastboot_fail("buffer overreads occured due to invalid sparse header");
2453 return;
2454 }
Channagoud Kadabif627cf82013-09-09 14:08:20 -07002455 fill_val = *(uint32_t *)data;
2456 data = (char *) data + sizeof(uint32_t);
Channagoud Kadabif627cf82013-09-09 14:08:20 -07002457
2458 for (i = 0; i < (sparse_header->blk_sz / sizeof(fill_val)); i++)
2459 {
2460 fill_buf[i] = fill_val;
2461 }
2462
wufeng.jiang813dc352015-06-02 23:02:46 -04002463 for (i = 0; i < chunk_header->chunk_sz; i++)
Channagoud Kadabif627cf82013-09-09 14:08:20 -07002464 {
Aparna Mallavarapu2ae741a2015-03-28 01:41:08 +05302465 /* Make sure that the data written to partition does not exceed partition size */
2466 if ((uint64_t)total_blocks * (uint64_t)sparse_header->blk_sz + sparse_header->blk_sz > size)
2467 {
2468 fastboot_fail("Chunk data size for fill type exceeds partition size");
2469 return;
2470 }
2471
Channagoud Kadabif627cf82013-09-09 14:08:20 -07002472 if(mmc_write(ptn + ((uint64_t)total_blocks*sparse_header->blk_sz),
2473 sparse_header->blk_sz,
2474 fill_buf))
2475 {
2476 fastboot_fail("flash write failure");
2477 free(fill_buf);
2478 return;
2479 }
2480
2481 total_blocks++;
2482 }
2483
2484 free(fill_buf);
2485 break;
2486
Ajay Dudani5c761132011-04-07 20:19:04 -07002487 case CHUNK_TYPE_DONT_CARE:
Aparna Mallavarapu2ae741a2015-03-28 01:41:08 +05302488 if(total_blocks > (UINT_MAX - chunk_header->chunk_sz)) {
2489 fastboot_fail("bogus size for chunk DONT CARE type");
2490 return;
2491 }
Kinson Chik kchik@codeaurora.orgda29b1e2011-05-06 17:36:39 -07002492 total_blocks += chunk_header->chunk_sz;
2493 break;
2494
Ajay Dudani5c761132011-04-07 20:19:04 -07002495 case CHUNK_TYPE_CRC:
2496 if(chunk_header->total_sz != sparse_header->chunk_hdr_sz)
2497 {
wufeng.jiang813dc352015-06-02 23:02:46 -04002498 fastboot_fail("Bogus chunk size for chunk type CRC");
Ajay Dudani5c761132011-04-07 20:19:04 -07002499 return;
2500 }
Aparna Mallavarapu2ae741a2015-03-28 01:41:08 +05302501 if(total_blocks > (UINT_MAX - chunk_header->chunk_sz)) {
2502 fastboot_fail("bogus size for chunk CRC type");
2503 return;
2504 }
Ajay Dudani5c761132011-04-07 20:19:04 -07002505 total_blocks += chunk_header->chunk_sz;
vijay kumar800255e2015-04-24 20:26:19 +05302506 if ((uint32_t)data > UINT_MAX - chunk_data_sz) {
2507 fastboot_fail("integer overflow occured");
2508 return;
2509 }
wufeng.jiang813dc352015-06-02 23:02:46 -04002510 data += (uint32_t)chunk_data_sz;
vijay kumar800255e2015-04-24 20:26:19 +05302511 if (data_end < (uint32_t)data) {
2512 fastboot_fail("buffer overreads occured due to invalid sparse header");
2513 return;
2514 }
Ajay Dudani5c761132011-04-07 20:19:04 -07002515 break;
2516
Kinson Chik kchik@codeaurora.orgda29b1e2011-05-06 17:36:39 -07002517 default:
Channagoud Kadabif627cf82013-09-09 14:08:20 -07002518 dprintf(CRITICAL, "Unkown chunk type: %x\n",chunk_header->chunk_type);
Ajay Dudani5c761132011-04-07 20:19:04 -07002519 fastboot_fail("Unknown chunk type");
2520 return;
2521 }
2522 }
2523
Ajay Dudani0c6927b2011-05-18 11:12:16 -07002524 dprintf(INFO, "Wrote %d blocks, expected to write %d blocks\n",
2525 total_blocks, sparse_header->total_blks);
2526
2527 if(total_blocks != sparse_header->total_blks)
2528 {
2529 fastboot_fail("sparse image write failure");
2530 }
Ajay Dudani5c761132011-04-07 20:19:04 -07002531
2532 fastboot_okay("");
2533 return;
2534}
2535
2536void cmd_flash_mmc(const char *arg, void *data, unsigned sz)
2537{
2538 sparse_header_t *sparse_header;
Ajay Dudanide984792015-03-02 09:57:41 -08002539 meta_header_t *meta_header;
Ajay Dudani5c761132011-04-07 20:19:04 -07002540
kchik@codeaurora.orgbce18ea2011-04-18 20:22:28 -07002541#ifdef SSD_ENABLE
Veera Sundaram Sankaranf9915462014-12-09 11:54:59 -08002542 /* 8 Byte Magic + 2048 Byte xml + Encrypted Data */
2543 unsigned int *magic_number = (unsigned int *) data;
sundarajan srinivasand4b1c482013-02-27 14:15:43 -08002544 int ret=0;
2545 uint32 major_version=0;
2546 uint32 minor_version=0;
2547
2548 ret = scm_svc_version(&major_version,&minor_version);
2549 if(!ret)
2550 {
2551 if(major_version >= 2)
2552 {
Amir Samuelovbb65ce02013-05-05 12:20:18 +03002553 if( !strcmp(arg, "ssd") || !strcmp(arg, "tqs") )
sundarajan srinivasand4b1c482013-02-27 14:15:43 -08002554 {
2555 ret = encrypt_scm((uint32 **) &data, &sz);
2556 if (ret != 0) {
2557 dprintf(CRITICAL, "ERROR: Encryption Failure\n");
2558 return;
2559 }
2560
Amir Samuelovbb65ce02013-05-05 12:20:18 +03002561 /* Protect only for SSD */
2562 if (!strcmp(arg, "ssd")) {
2563 ret = scm_protect_keystore((uint32 *) data, sz);
2564 if (ret != 0) {
2565 dprintf(CRITICAL, "ERROR: scm_protect_keystore Failed\n");
2566 return;
2567 }
sundarajan srinivasand4b1c482013-02-27 14:15:43 -08002568 }
2569 }
2570 else
2571 {
2572 ret = decrypt_scm_v2((uint32 **) &data, &sz);
2573 if(ret != 0)
2574 {
2575 dprintf(CRITICAL,"ERROR: Decryption Failure\n");
2576 return;
2577 }
2578 }
2579 }
2580 else
2581 {
2582 if (magic_number[0] == DECRYPT_MAGIC_0 &&
2583 magic_number[1] == DECRYPT_MAGIC_1)
2584 {
2585 ret = decrypt_scm((uint32 **) &data, &sz);
2586 if (ret != 0) {
2587 dprintf(CRITICAL, "ERROR: Invalid secure image\n");
2588 return;
2589 }
2590 }
2591 else if (magic_number[0] == ENCRYPT_MAGIC_0 &&
2592 magic_number[1] == ENCRYPT_MAGIC_1)
2593 {
2594 ret = encrypt_scm((uint32 **) &data, &sz);
2595 if (ret != 0) {
2596 dprintf(CRITICAL, "ERROR: Encryption Failure\n");
2597 return;
2598 }
2599 }
kchik@codeaurora.orgbce18ea2011-04-18 20:22:28 -07002600 }
2601 }
sundarajan srinivasand4b1c482013-02-27 14:15:43 -08002602 else
Neeti Desai127b9e02012-03-20 16:11:23 -07002603 {
sundarajan srinivasand4b1c482013-02-27 14:15:43 -08002604 dprintf(CRITICAL,"INVALID SVC Version\n");
2605 return;
Neeti Desai127b9e02012-03-20 16:11:23 -07002606 }
sundarajan srinivasand4b1c482013-02-27 14:15:43 -08002607#endif /* SSD_ENABLE */
Neeti Desai127b9e02012-03-20 16:11:23 -07002608
Shashank Mittald3e54dd2014-08-28 15:24:02 -07002609#if VERIFIED_BOOT
Channagoud Kadabi35297672015-06-13 11:09:49 -07002610 if (target_build_variant_user())
Shashank Mittald3e54dd2014-08-28 15:24:02 -07002611 {
Channagoud Kadabi35297672015-06-13 11:09:49 -07002612 if(!device.is_unlocked)
Shashank Mittald3e54dd2014-08-28 15:24:02 -07002613 {
Channagoud Kadabi35297672015-06-13 11:09:49 -07002614 fastboot_fail("device is locked. Cannot flash images");
Shashank Mittald3e54dd2014-08-28 15:24:02 -07002615 return;
2616 }
Channagoud Kadabi35297672015-06-13 11:09:49 -07002617 if(!device.is_unlocked && device.is_verified)
2618 {
2619 if(!boot_verify_flash_allowed(arg))
2620 {
2621 fastboot_fail("cannot flash this partition in verified state");
2622 return;
2623 }
2624 }
Shashank Mittald3e54dd2014-08-28 15:24:02 -07002625 }
2626#endif
2627
kchik@codeaurora.orgbce18ea2011-04-18 20:22:28 -07002628 sparse_header = (sparse_header_t *) data;
Ajay Dudanide984792015-03-02 09:57:41 -08002629 meta_header = (meta_header_t *) data;
2630 if (sparse_header->magic == SPARSE_HEADER_MAGIC)
Ajay Dudani5c761132011-04-07 20:19:04 -07002631 cmd_flash_mmc_sparse_img(arg, data, sz);
Ajay Dudanide984792015-03-02 09:57:41 -08002632 else if (meta_header->magic == META_HEADER_MAGIC)
2633 cmd_flash_meta_img(arg, data, sz);
2634 else
2635 cmd_flash_mmc_img(arg, data, sz);
Ajay Dudani5c761132011-04-07 20:19:04 -07002636 return;
2637}
2638
Tanya Brokhman84eaaf62015-02-24 21:57:06 +02002639void cmd_updatevol(const char *vol_name, void *data, unsigned sz)
2640{
2641 struct ptentry *sys_ptn;
2642 struct ptable *ptable;
2643
2644 ptable = flash_get_ptable();
2645 if (ptable == NULL) {
2646 fastboot_fail("partition table doesn't exist");
2647 return;
2648 }
2649
2650 sys_ptn = ptable_find(ptable, "system");
2651 if (sys_ptn == NULL) {
2652 fastboot_fail("system partition not found");
2653 return;
2654 }
2655
2656 sz = ROUND_TO_PAGE(sz, page_mask);
2657 if (update_ubi_vol(sys_ptn, vol_name, data, sz))
2658 fastboot_fail("update_ubi_vol failed");
2659 else
2660 fastboot_okay("");
2661}
2662
Sridhar Parasurame94e8152014-10-24 14:06:03 -07002663void cmd_flash_nand(const char *arg, void *data, unsigned sz)
Dima Zavin214cc642009-01-26 11:16:21 -08002664{
2665 struct ptentry *ptn;
2666 struct ptable *ptable;
2667 unsigned extra = 0;
2668
2669 ptable = flash_get_ptable();
2670 if (ptable == NULL) {
2671 fastboot_fail("partition table doesn't exist");
2672 return;
2673 }
2674
2675 ptn = ptable_find(ptable, arg);
2676 if (ptn == NULL) {
Tanya Brokhman84eaaf62015-02-24 21:57:06 +02002677 dprintf(INFO, "unknown partition name (%s). Trying updatevol\n",
2678 arg);
2679 cmd_updatevol(arg, data, sz);
Dima Zavin214cc642009-01-26 11:16:21 -08002680 return;
2681 }
2682
2683 if (!strcmp(ptn->name, "boot") || !strcmp(ptn->name, "recovery")) {
2684 if (memcmp((void *)data, BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
2685 fastboot_fail("image is not a boot image");
2686 return;
2687 }
2688 }
2689
Amol Jadi5c61a952012-05-04 17:05:35 -07002690 if (!strcmp(ptn->name, "system")
Deepa Dinamani13e32c42012-03-12 14:34:17 -07002691 || !strcmp(ptn->name, "userdata")
2692 || !strcmp(ptn->name, "persist")
Sundarajan Srinivasanb063a852013-11-19 14:02:27 -08002693 || !strcmp(ptn->name, "recoveryfs")
Sundarajan Srinivasan595b71e2013-11-05 12:44:34 -08002694 || !strcmp(ptn->name, "modem"))
Tanya Brokhman1c94f1a2015-02-15 09:05:03 +02002695 extra = 1;
Sundarajan Srinivasan595b71e2013-11-05 12:44:34 -08002696 else
Shashank Mittaldcc2e352009-11-19 19:11:16 -08002697 sz = ROUND_TO_PAGE(sz, page_mask);
Dima Zavin214cc642009-01-26 11:16:21 -08002698
2699 dprintf(INFO, "writing %d bytes to '%s'\n", sz, ptn->name);
Tanya Brokhman1c94f1a2015-02-15 09:05:03 +02002700 if (!memcmp((void *)data, UBI_MAGIC, UBI_MAGIC_SIZE)) {
2701 if (flash_ubi_img(ptn, data, sz)) {
2702 fastboot_fail("flash write failure");
2703 return;
2704 }
2705 } else {
2706 if (flash_write(ptn, extra, data, sz)) {
2707 fastboot_fail("flash write failure");
2708 return;
2709 }
Dima Zavin214cc642009-01-26 11:16:21 -08002710 }
2711 dprintf(INFO, "partition '%s' updated\n", ptn->name);
2712 fastboot_okay("");
2713}
2714
Sridhar Parasurame94e8152014-10-24 14:06:03 -07002715void cmd_flash(const char *arg, void *data, unsigned sz)
2716{
2717 if(target_is_emmc_boot())
2718 cmd_flash_mmc(arg, data, sz);
2719 else
2720 cmd_flash_nand(arg, data, sz);
2721}
2722
Dima Zavin214cc642009-01-26 11:16:21 -08002723void cmd_continue(const char *arg, void *data, unsigned sz)
2724{
2725 fastboot_okay("");
Amol Jadi7c4316c2013-10-07 14:19:26 -07002726 fastboot_stop();
Shashank Mittald3e54dd2014-08-28 15:24:02 -07002727
Shashank Mittald8c42bf2010-06-09 15:44:28 -07002728 if (target_is_emmc_boot())
2729 {
2730 boot_linux_from_mmc();
2731 }
2732 else
2733 {
2734 boot_linux_from_flash();
2735 }
Dima Zavin214cc642009-01-26 11:16:21 -08002736}
2737
Chandan Uddaraju94183c02010-01-15 15:13:59 -08002738void cmd_reboot(const char *arg, void *data, unsigned sz)
2739{
Shashank Mittald8c42bf2010-06-09 15:44:28 -07002740 dprintf(INFO, "rebooting the device\n");
Chandan Uddaraju94183c02010-01-15 15:13:59 -08002741 fastboot_okay("");
2742 reboot_device(0);
2743}
2744
2745void cmd_reboot_bootloader(const char *arg, void *data, unsigned sz)
2746{
Shashank Mittald8c42bf2010-06-09 15:44:28 -07002747 dprintf(INFO, "rebooting the device\n");
Chandan Uddaraju94183c02010-01-15 15:13:59 -08002748 fastboot_okay("");
2749 reboot_device(FASTBOOT_MODE);
2750}
2751
Ameya Thakur11cf1a62013-08-05 12:44:48 -07002752void cmd_oem_enable_charger_screen(const char *arg, void *data, unsigned size)
2753{
2754 dprintf(INFO, "Enabling charger screen check\n");
2755 device.charger_screen_enabled = 1;
2756 write_device_info(&device);
2757 fastboot_okay("");
2758}
2759
2760void cmd_oem_disable_charger_screen(const char *arg, void *data, unsigned size)
2761{
2762 dprintf(INFO, "Disabling charger screen check\n");
2763 device.charger_screen_enabled = 0;
2764 write_device_info(&device);
2765 fastboot_okay("");
2766}
2767
Unnati Gandhi62c8ab82014-01-24 11:01:01 +05302768void cmd_oem_select_display_panel(const char *arg, void *data, unsigned size)
2769{
2770 dprintf(INFO, "Selecting display panel %s\n", arg);
2771 if (arg)
2772 strlcpy(device.display_panel, arg,
2773 sizeof(device.display_panel));
2774 write_device_info(&device);
2775 fastboot_okay("");
2776}
2777
Shashank Mittal162244e2011-08-08 19:01:25 -07002778void cmd_oem_unlock(const char *arg, void *data, unsigned sz)
2779{
vijay kumarc65876c2015-04-24 13:29:16 +05302780 if(!is_allow_unlock) {
2781 fastboot_fail("oem unlock is not allowed");
2782 return;
2783 }
2784
2785 display_fbcon_message("Oem Unlock requested");
2786 fastboot_fail("Need wipe userdata. Do 'fastboot oem unlock-go'");
2787}
2788
2789void cmd_oem_unlock_go(const char *arg, void *data, unsigned sz)
2790{
Shashank Mittald3e54dd2014-08-28 15:24:02 -07002791 if(!device.is_unlocked || device.is_verified)
Shashank Mittal162244e2011-08-08 19:01:25 -07002792 {
vijay kumarc65876c2015-04-24 13:29:16 +05302793 if(!is_allow_unlock) {
2794 fastboot_fail("oem unlock is not allowed");
2795 return;
2796 }
2797
Shashank Mittal162244e2011-08-08 19:01:25 -07002798 device.is_unlocked = 1;
Shashank Mittald3e54dd2014-08-28 15:24:02 -07002799 device.is_verified = 0;
2800 write_device_info(&device);
vijay kumarc65876c2015-04-24 13:29:16 +05302801
2802 struct recovery_message msg;
2803 snprintf(msg.recovery, sizeof(msg.recovery), "recovery\n--wipe_data");
2804 write_misc(0, &msg, sizeof(msg));
2805
2806 fastboot_okay("");
2807 reboot_device(RECOVERY_MODE);
Shashank Mittald3e54dd2014-08-28 15:24:02 -07002808 }
2809 fastboot_okay("");
2810}
2811
2812void cmd_oem_lock(const char *arg, void *data, unsigned sz)
2813{
2814 /* TODO: Wipe user data */
2815 if(device.is_unlocked || device.is_verified)
2816 {
2817 device.is_unlocked = 0;
2818 device.is_verified = 0;
2819 write_device_info(&device);
2820 }
2821 fastboot_okay("");
2822}
2823
2824void cmd_oem_verified(const char *arg, void *data, unsigned sz)
2825{
2826 /* TODO: Wipe user data */
2827 if(device.is_unlocked || !device.is_verified)
2828 {
2829 device.is_unlocked = 0;
2830 device.is_verified = 1;
Shashank Mittal162244e2011-08-08 19:01:25 -07002831 write_device_info(&device);
2832 }
2833 fastboot_okay("");
2834}
2835
Shashank Mittala0032282011-08-26 14:50:11 -07002836void cmd_oem_devinfo(const char *arg, void *data, unsigned sz)
2837{
Unnati Gandhi62c8ab82014-01-24 11:01:01 +05302838 char response[128];
Ameya Thakur11cf1a62013-08-05 12:44:48 -07002839 snprintf(response, sizeof(response), "\tDevice tampered: %s", (device.is_tampered ? "true" : "false"));
Shashank Mittala0032282011-08-26 14:50:11 -07002840 fastboot_info(response);
Ameya Thakur11cf1a62013-08-05 12:44:48 -07002841 snprintf(response, sizeof(response), "\tDevice unlocked: %s", (device.is_unlocked ? "true" : "false"));
2842 fastboot_info(response);
2843 snprintf(response, sizeof(response), "\tCharger screen enabled: %s", (device.charger_screen_enabled ? "true" : "false"));
Shashank Mittala0032282011-08-26 14:50:11 -07002844 fastboot_info(response);
Unnati Gandhi62c8ab82014-01-24 11:01:01 +05302845 snprintf(response, sizeof(response), "\tDisplay panel: %s", (device.display_panel));
2846 fastboot_info(response);
Shashank Mittala0032282011-08-26 14:50:11 -07002847 fastboot_okay("");
2848}
2849
Channagoud Kadabi4c4884e2013-04-09 17:12:13 -07002850void cmd_preflash(const char *arg, void *data, unsigned sz)
2851{
2852 fastboot_okay("");
2853}
2854
Mao Flynn7b379f32015-04-20 00:28:30 +08002855static uint8_t logo_header[LOGO_IMG_HEADER_SIZE];
Aparna Mallavarapuad8c1ec2013-08-23 17:55:47 +05302856
Mao Flynn7b379f32015-04-20 00:28:30 +08002857int splash_screen_check_header(logo_img_header *header)
Aparna Mallavarapuad8c1ec2013-08-23 17:55:47 +05302858{
Mao Flynn7b379f32015-04-20 00:28:30 +08002859 if (memcmp(header->magic, LOGO_IMG_MAGIC, 8))
Aparna Mallavarapuad8c1ec2013-08-23 17:55:47 +05302860 return -1;
Mao Flynn7b379f32015-04-20 00:28:30 +08002861 if (header->width == 0 || header->height == 0)
Aparna Mallavarapuad8c1ec2013-08-23 17:55:47 +05302862 return -1;
2863 return 0;
2864}
2865
Mao Flynn7b379f32015-04-20 00:28:30 +08002866int splash_screen_flash()
Chandan Uddaraju2943fd62010-06-21 10:56:39 -07002867{
2868 struct ptentry *ptn;
2869 struct ptable *ptable;
Mao Flynn7b379f32015-04-20 00:28:30 +08002870 struct logo_img_header *header;
Chandan Uddaraju2943fd62010-06-21 10:56:39 -07002871 struct fbcon_config *fb_display = NULL;
Channagoud Kadabib3ccf5c2014-12-03 12:39:29 -08002872
Aparna Mallavarapuad8c1ec2013-08-23 17:55:47 +05302873 ptable = flash_get_ptable();
2874 if (ptable == NULL) {
Mao Flynn7b379f32015-04-20 00:28:30 +08002875 dprintf(CRITICAL, "ERROR: Partition table not found\n");
2876 return -1;
Aparna Mallavarapuad8c1ec2013-08-23 17:55:47 +05302877 }
Mao Flynn7b379f32015-04-20 00:28:30 +08002878
Aparna Mallavarapuad8c1ec2013-08-23 17:55:47 +05302879 ptn = ptable_find(ptable, "splash");
2880 if (ptn == NULL) {
2881 dprintf(CRITICAL, "ERROR: splash Partition not found\n");
Mao Flynn7b379f32015-04-20 00:28:30 +08002882 return -1;
Aparna Mallavarapuad8c1ec2013-08-23 17:55:47 +05302883 }
Mao Flynn7b379f32015-04-20 00:28:30 +08002884 if (flash_read(ptn, 0, (void *)logo_header, LOGO_IMG_HEADER_SIZE)) {
Aparna Mallavarapuad8c1ec2013-08-23 17:55:47 +05302885 dprintf(CRITICAL, "ERROR: Cannot read boot image header\n");
Mao Flynn7b379f32015-04-20 00:28:30 +08002886 return -1;
Aparna Mallavarapuad8c1ec2013-08-23 17:55:47 +05302887 }
2888
Mao Flynn7b379f32015-04-20 00:28:30 +08002889 header = (struct logo_img_header *)logo_header;
2890 if (splash_screen_check_header(header)) {
Aparna Mallavarapuad8c1ec2013-08-23 17:55:47 +05302891 dprintf(CRITICAL, "ERROR: Boot image header invalid\n");
Mao Flynn7b379f32015-04-20 00:28:30 +08002892 return -1;
Aparna Mallavarapuad8c1ec2013-08-23 17:55:47 +05302893 }
2894
2895 fb_display = fbcon_display();
2896 if (fb_display) {
Mao Flynn7b379f32015-04-20 00:28:30 +08002897 if (header->type && (header->blocks != 0)) { // RLE24 compressed data
2898 uint8_t *base = (uint8_t *) fb_display->base + LOGO_IMG_OFFSET;
2899
2900 /* if the logo is full-screen size, remove "fbcon_clear()" */
2901 if ((header->width != fb_display->width)
2902 || (header->height != fb_display->height))
2903 fbcon_clear();
2904
2905 if (flash_read(ptn + LOGO_IMG_HEADER_SIZE, 0,
2906 (uint32_t *)base,
2907 (header->blocks * 512))) {
2908 dprintf(CRITICAL, "ERROR: Cannot read splash image from partition\n");
2909 return -1;
2910 }
2911 fbcon_extract_to_screen(header, base);
2912 return 0;
Chandan Uddaraju2943fd62010-06-21 10:56:39 -07002913 }
Mao Flynn7b379f32015-04-20 00:28:30 +08002914
2915 if ((header->width != fb_display->width) || (header->height != fb_display->height)) {
2916 dprintf(CRITICAL, "Logo config doesn't match with fb config. Fall back default logo\n");
2917 return -1;
2918 }
2919
Vineet Bajaj99291ed2014-09-09 12:29:46 +05302920 uint8_t *base = (uint8_t *) fb_display->base;
Mao Flynn7b379f32015-04-20 00:28:30 +08002921 if (flash_read(ptn + LOGO_IMG_HEADER_SIZE, 0,
2922 (uint32_t *)base,
2923 ((((header->width * header->height * fb_display->bpp/8) + 511) >> 9) << 9))) {
Aparna Mallavarapuad8c1ec2013-08-23 17:55:47 +05302924 fbcon_clear();
Vineet Bajaj99291ed2014-09-09 12:29:46 +05302925 dprintf(CRITICAL, "ERROR: Cannot read splash image from partition\n");
Mao Flynn7b379f32015-04-20 00:28:30 +08002926 return -1;
Chandan Uddaraju2943fd62010-06-21 10:56:39 -07002927 }
Aparna Mallavarapuad8c1ec2013-08-23 17:55:47 +05302928 }
2929
Mao Flynn7b379f32015-04-20 00:28:30 +08002930 return 0;
Aparna Mallavarapuad8c1ec2013-08-23 17:55:47 +05302931}
2932
Mao Flynn7b379f32015-04-20 00:28:30 +08002933int splash_screen_mmc()
Aparna Mallavarapuad8c1ec2013-08-23 17:55:47 +05302934{
2935 int index = INVALID_PTN;
2936 unsigned long long ptn = 0;
2937 struct fbcon_config *fb_display = NULL;
Mao Flynn7b379f32015-04-20 00:28:30 +08002938 struct logo_img_header *header;
Mao Flynn1893a7f2015-06-03 12:03:36 +08002939 uint32_t blocksize, realsize, readsize;
2940 uint8_t *base;
Aparna Mallavarapuad8c1ec2013-08-23 17:55:47 +05302941
2942 index = partition_get_index("splash");
2943 if (index == 0) {
2944 dprintf(CRITICAL, "ERROR: splash Partition table not found\n");
Mao Flynn7b379f32015-04-20 00:28:30 +08002945 return -1;
Aparna Mallavarapuad8c1ec2013-08-23 17:55:47 +05302946 }
2947
2948 ptn = partition_get_offset(index);
2949 if (ptn == 0) {
2950 dprintf(CRITICAL, "ERROR: splash Partition invalid\n");
Mao Flynn7b379f32015-04-20 00:28:30 +08002951 return -1;
Aparna Mallavarapuad8c1ec2013-08-23 17:55:47 +05302952 }
2953
Mao Flynn1893a7f2015-06-03 12:03:36 +08002954 mmc_set_lun(partition_get_lun(index));
2955
2956 blocksize = mmc_get_device_blocksize();
2957 if (blocksize == 0) {
2958 dprintf(CRITICAL, "ERROR:splash Partition invalid blocksize\n");
2959 return -1;
2960 }
2961
2962 fb_display = fbcon_display();
2963 base = (uint8_t *) fb_display->base;
2964
2965 if (mmc_read(ptn, (uint32_t *)(base + LOGO_IMG_OFFSET), blocksize)) {
Aparna Mallavarapuad8c1ec2013-08-23 17:55:47 +05302966 dprintf(CRITICAL, "ERROR: Cannot read splash image header\n");
Mao Flynn7b379f32015-04-20 00:28:30 +08002967 return -1;
Aparna Mallavarapuad8c1ec2013-08-23 17:55:47 +05302968 }
2969
Mao Flynn1893a7f2015-06-03 12:03:36 +08002970 header = (struct logo_img_header *)(base + LOGO_IMG_OFFSET);
Mao Flynn7b379f32015-04-20 00:28:30 +08002971 if (splash_screen_check_header(header)) {
Aparna Mallavarapuad8c1ec2013-08-23 17:55:47 +05302972 dprintf(CRITICAL, "ERROR: Splash image header invalid\n");
Mao Flynn7b379f32015-04-20 00:28:30 +08002973 return -1;
Aparna Mallavarapuad8c1ec2013-08-23 17:55:47 +05302974 }
2975
Aparna Mallavarapuad8c1ec2013-08-23 17:55:47 +05302976 if (fb_display) {
Mao Flynn1893a7f2015-06-03 12:03:36 +08002977 if (header->type && (header->blocks != 0)) { /* 1 RLE24 compressed data */
2978 base += LOGO_IMG_OFFSET;
Mao Flynn7b379f32015-04-20 00:28:30 +08002979
Mao Flynn1893a7f2015-06-03 12:03:36 +08002980 realsize = header->blocks * 512;
2981 readsize = ROUNDUP((realsize + LOGO_IMG_HEADER_SIZE), blocksize) - blocksize;
2982
2983 /* if the logo is not full-screen size, clean screen */
Mao Flynn7b379f32015-04-20 00:28:30 +08002984 if ((header->width != fb_display->width)
2985 || (header->height != fb_display->height))
2986 fbcon_clear();
2987
Mao Flynn1893a7f2015-06-03 12:03:36 +08002988 if (mmc_read(ptn + blocksize, (uint32_t *)(base + blocksize), readsize)) {
Mao Flynn7b379f32015-04-20 00:28:30 +08002989 dprintf(CRITICAL, "ERROR: Cannot read splash image from partition\n");
2990 return -1;
2991 }
Mao Flynn7b379f32015-04-20 00:28:30 +08002992
Mao Flynn1893a7f2015-06-03 12:03:36 +08002993 fbcon_extract_to_screen(header, (base + LOGO_IMG_HEADER_SIZE));
2994 } else { /* 2 Raw BGR data */
Aparna Mallavarapuad8c1ec2013-08-23 17:55:47 +05302995
Mao Flynn1893a7f2015-06-03 12:03:36 +08002996 if ((header->width != fb_display->width) || (header->height != fb_display->height)) {
2997 dprintf(CRITICAL, "Logo config doesn't match with fb config. Fall back default logo\n");
2998 return -1;
2999 }
3000
3001 realsize = header->width * header->height * fb_display->bpp / 8;
3002 readsize = ROUNDUP((realsize + LOGO_IMG_HEADER_SIZE), blocksize) - blocksize;
3003
3004 if (blocksize == LOGO_IMG_HEADER_SIZE) { /* read the content directly */
3005 if (mmc_read((ptn + LOGO_IMG_HEADER_SIZE), (uint32_t *)base, readsize)) {
3006 fbcon_clear();
3007 dprintf(CRITICAL, "ERROR: Cannot read splash image from partition\n");
3008 return -1;
3009 }
3010 } else {
3011 if (mmc_read(ptn + blocksize ,
3012 (uint32_t *)(base + LOGO_IMG_OFFSET + blocksize), readsize)) {
3013 dprintf(CRITICAL, "ERROR: Cannot read splash image from partition\n");
3014 return -1;
3015 }
3016 memmove(base, (base + LOGO_IMG_OFFSET + LOGO_IMG_HEADER_SIZE), realsize);
3017 }
3018 }
Aparna Mallavarapuad8c1ec2013-08-23 17:55:47 +05303019 }
3020
Mao Flynn7b379f32015-04-20 00:28:30 +08003021 return 0;
Aparna Mallavarapuad8c1ec2013-08-23 17:55:47 +05303022}
3023
Mao Flynn7b379f32015-04-20 00:28:30 +08003024int fetch_image_from_partition()
Aparna Mallavarapuad8c1ec2013-08-23 17:55:47 +05303025{
3026 if (target_is_emmc_boot()) {
3027 return splash_screen_mmc();
3028 } else {
3029 return splash_screen_flash();
Chandan Uddaraju2943fd62010-06-21 10:56:39 -07003030 }
3031}
3032
Channagoud Kadabi4c4884e2013-04-09 17:12:13 -07003033/* Get the size from partiton name */
3034static void get_partition_size(const char *arg, char *response)
3035{
3036 uint64_t ptn = 0;
3037 uint64_t size;
3038 int index = INVALID_PTN;
3039
3040 index = partition_get_index(arg);
3041
3042 if (index == INVALID_PTN)
3043 {
3044 dprintf(CRITICAL, "Invalid partition index\n");
3045 return;
3046 }
3047
3048 ptn = partition_get_offset(index);
3049
3050 if(!ptn)
3051 {
3052 dprintf(CRITICAL, "Invalid partition name %s\n", arg);
3053 return;
3054 }
3055
3056 size = partition_get_size(index);
3057
3058 snprintf(response, MAX_RSP_SIZE, "\t 0x%llx", size);
3059 return;
3060}
3061
3062/*
3063 * Publish the partition type & size info
3064 * fastboot getvar will publish the required information.
3065 * fastboot getvar partition_size:<partition_name>: partition size in hex
3066 * fastboot getvar partition_type:<partition_name>: partition type (ext/fat)
3067 */
3068static void publish_getvar_partition_info(struct getvar_partition_info *info, uint8_t num_parts)
3069{
3070 uint8_t i;
3071
3072 for (i = 0; i < num_parts; i++) {
3073 get_partition_size(info[i].part_name, info[i].size_response);
3074
3075 if (strlcat(info[i].getvar_size, info[i].part_name, MAX_GET_VAR_NAME_SIZE) >= MAX_GET_VAR_NAME_SIZE)
3076 {
3077 dprintf(CRITICAL, "partition size name truncated\n");
3078 return;
3079 }
3080 if (strlcat(info[i].getvar_type, info[i].part_name, MAX_GET_VAR_NAME_SIZE) >= MAX_GET_VAR_NAME_SIZE)
3081 {
3082 dprintf(CRITICAL, "partition type name truncated\n");
3083 return;
3084 }
3085
3086 /* publish partition size & type info */
3087 fastboot_publish((const char *) info[i].getvar_size, (const char *) info[i].size_response);
3088 fastboot_publish((const char *) info[i].getvar_type, (const char *) info[i].type_response);
3089 }
3090}
3091
Amol Jadi5edf3552013-07-23 14:15:34 -07003092/* register commands and variables for fastboot */
3093void aboot_fastboot_register_commands(void)
3094{
Sridhar Parasurame94e8152014-10-24 14:06:03 -07003095 int i;
Amol Jadi5edf3552013-07-23 14:15:34 -07003096
Sridhar Parasurame94e8152014-10-24 14:06:03 -07003097 struct fastboot_cmd_desc cmd_list[] = {
3098 /* By default the enabled list is empty. */
3099 {"", NULL},
3100 /* move commands enclosed within the below ifndef to here
3101 * if they need to be enabled in user build.
3102 */
3103#ifndef DISABLE_FASTBOOT_CMDS
3104 /* Register the following commands only for non-user builds */
3105 {"flash:", cmd_flash},
3106 {"erase:", cmd_erase},
3107 {"boot", cmd_boot},
3108 {"continue", cmd_continue},
3109 {"reboot", cmd_reboot},
3110 {"reboot-bootloader", cmd_reboot_bootloader},
3111 {"oem unlock", cmd_oem_unlock},
vijay kumarc65876c2015-04-24 13:29:16 +05303112 {"oem unlock-go", cmd_oem_unlock_go},
Sridhar Parasurame94e8152014-10-24 14:06:03 -07003113 {"oem lock", cmd_oem_lock},
3114 {"oem verified", cmd_oem_verified},
3115 {"oem device-info", cmd_oem_devinfo},
3116 {"preflash", cmd_preflash},
3117 {"oem enable-charger-screen", cmd_oem_enable_charger_screen},
3118 {"oem disable-charger-screen", cmd_oem_disable_charger_screen},
Aravind Venkateswaranbcca9b12014-11-04 17:04:01 -08003119 {"oem select-display-panel", cmd_oem_select_display_panel},
Sridhar Parasurame94e8152014-10-24 14:06:03 -07003120#endif
3121 };
3122
3123 int fastboot_cmds_count = sizeof(cmd_list)/sizeof(cmd_list[0]);
3124 for (i = 1; i < fastboot_cmds_count; i++)
3125 fastboot_register(cmd_list[i].name,cmd_list[i].cb);
3126
Amol Jadi5edf3552013-07-23 14:15:34 -07003127 /* publish variables and their values */
3128 fastboot_publish("product", TARGET(BOARD));
3129 fastboot_publish("kernel", "lk");
3130 fastboot_publish("serialno", sn_buf);
3131
3132 /*
3133 * partition info is supported only for emmc partitions
3134 * Calling this for NAND prints some error messages which
3135 * is harmless but misleading. Avoid calling this for NAND
3136 * devices.
3137 */
3138 if (target_is_emmc_boot())
3139 publish_getvar_partition_info(part_info, ARRAY_SIZE(part_info));
3140
3141 /* Max download size supported */
Ameya Thakur11cf1a62013-08-05 12:44:48 -07003142 snprintf(max_download_size, MAX_RSP_SIZE, "\t0x%x",
3143 target_get_max_flash_size());
Amol Jadi5edf3552013-07-23 14:15:34 -07003144 fastboot_publish("max-download-size", (const char *) max_download_size);
Ameya Thakur11cf1a62013-08-05 12:44:48 -07003145 /* Is the charger screen check enabled */
3146 snprintf(charger_screen_enabled, MAX_RSP_SIZE, "%d",
3147 device.charger_screen_enabled);
3148 fastboot_publish("charger-screen-enabled",
3149 (const char *) charger_screen_enabled);
Unnati Gandhi62c8ab82014-01-24 11:01:01 +05303150 snprintf(panel_display_mode, MAX_RSP_SIZE, "%s",
3151 device.display_panel);
3152 fastboot_publish("display-panel",
3153 (const char *) panel_display_mode);
Channagoud Kadabiaafbbfc2015-03-04 17:52:56 -08003154 fastboot_publish("version-bootloader", (const char *) device.bootloader_version);
3155 fastboot_publish("version-baseband", (const char *) device.radio_version);
Amol Jadi5edf3552013-07-23 14:15:34 -07003156}
3157
Brian Swetland9c4c0752009-01-25 16:23:50 -08003158void aboot_init(const struct app_descriptor *app)
3159{
Shashank Mittal4f99a882010-02-01 13:58:50 -08003160 unsigned reboot_mode = 0;
lijuang72875802015-02-10 10:35:12 +08003161 unsigned hard_reboot_mode = 0;
Pavel Nedev5d91d412013-04-29 11:34:24 +03003162 bool boot_into_fastboot = false;
Chandan Uddarajubedca152010-06-02 23:05:15 -07003163
Channagoud Kadabi749b0f82013-09-10 22:36:02 -07003164 /* Setup page size information for nv storage */
Shashank Mittald8c42bf2010-06-09 15:44:28 -07003165 if (target_is_emmc_boot())
3166 {
Channagoud Kadabi749b0f82013-09-10 22:36:02 -07003167 page_size = mmc_page_size();
Shashank Mittald8c42bf2010-06-09 15:44:28 -07003168 page_mask = page_size - 1;
3169 }
3170 else
3171 {
3172 page_size = flash_page_size();
3173 page_mask = page_size - 1;
3174 }
3175
Deepa Dinamani0e163a42013-05-24 17:08:15 -07003176 ASSERT((MEMBASE + MEMSIZE) > MEMBASE);
3177
Ameya Thakur11cf1a62013-08-05 12:44:48 -07003178 read_device_info(&device);
vijay kumarc65876c2015-04-24 13:29:16 +05303179 read_allow_oem_unlock(&device);
Shashank Mittal162244e2011-08-08 19:01:25 -07003180
Aravind Venkateswaran8f076242014-02-25 16:25:30 -08003181 /* Display splash screen if enabled */
3182#if DISPLAY_SPLASH_SCREEN
lijuang99c02d82015-02-13 19:04:34 +08003183#if NO_ALARM_DISPLAY
3184 if (!check_alarm_boot()) {
Aravind Venkateswaran8f076242014-02-25 16:25:30 -08003185#endif
lijuang99c02d82015-02-13 19:04:34 +08003186 dprintf(SPEW, "Display Init: Start\n");
3187 target_display_init(device.display_panel);
3188 dprintf(SPEW, "Display Init: Done\n");
3189#if NO_ALARM_DISPLAY
3190 }
3191#endif
3192#endif
Aravind Venkateswaran8f076242014-02-25 16:25:30 -08003193
Greg Griscod6250552011-06-29 14:40:23 -07003194 target_serialno((unsigned char *) sn_buf);
Ajay Dudanib06c05f2011-05-12 14:46:10 -07003195 dprintf(SPEW,"serial number: %s\n",sn_buf);
Subbaraman Narayanamurthyf17b4ae2011-02-16 20:19:56 -08003196
Dhaval Patel223ec952013-07-18 14:49:44 -07003197 memset(display_panel_buf, '\0', MAX_PANEL_BUF_SIZE);
3198
Matthew Qindefd5562014-07-11 18:02:40 +08003199 /*
3200 * Check power off reason if user force reset,
3201 * if yes phone will do normal boot.
3202 */
3203 if (is_user_force_reset())
3204 goto normal_boot;
3205
Chandan Uddaraju2943fd62010-06-21 10:56:39 -07003206 /* Check if we should do something other than booting up */
Ameya Thakur0b9c2442013-05-10 13:22:56 -07003207 if (keys_get_state(KEY_VOLUMEUP) && keys_get_state(KEY_VOLUMEDOWN))
Subbaraman Narayanamurthy0e445b02011-06-19 21:34:46 -07003208 {
Pavel Nedeva4c9d3a2013-05-15 14:42:34 +03003209 dprintf(ALWAYS,"dload mode key sequence detected\n");
3210 if (set_download_mode(EMERGENCY_DLOAD))
Ameya Thakur0b9c2442013-05-10 13:22:56 -07003211 {
Pavel Nedeva4c9d3a2013-05-15 14:42:34 +03003212 dprintf(CRITICAL,"dload mode not supported by target\n");
Ameya Thakur0b9c2442013-05-10 13:22:56 -07003213 }
3214 else
3215 {
Aparna Mallavarapu0751f7f2014-04-01 22:40:39 +05303216 reboot_device(DLOAD);
Pavel Nedeva4c9d3a2013-05-15 14:42:34 +03003217 dprintf(CRITICAL,"Failed to reboot into dload mode\n");
Ameya Thakur0b9c2442013-05-10 13:22:56 -07003218 }
3219 boot_into_fastboot = true;
3220 }
3221 if (!boot_into_fastboot)
3222 {
3223 if (keys_get_state(KEY_HOME) || keys_get_state(KEY_VOLUMEUP))
3224 boot_into_recovery = 1;
3225 if (!boot_into_recovery &&
3226 (keys_get_state(KEY_BACK) || keys_get_state(KEY_VOLUMEDOWN)))
Pavel Nedev5d91d412013-04-29 11:34:24 +03003227 boot_into_fastboot = true;
Subbaraman Narayanamurthy0e445b02011-06-19 21:34:46 -07003228 }
Shashank Mittald8c42bf2010-06-09 15:44:28 -07003229 #if NO_KEYPAD_DRIVER
Kinson Chik0b1c8162011-08-31 16:31:57 -07003230 if (fastboot_trigger())
Pavel Nedev5d91d412013-04-29 11:34:24 +03003231 boot_into_fastboot = true;
Shashank Mittald8c42bf2010-06-09 15:44:28 -07003232 #endif
Chandan Uddarajubedca152010-06-02 23:05:15 -07003233
Ajay Dudani77421292010-10-27 19:34:06 -07003234 reboot_mode = check_reboot_mode();
lijuang72875802015-02-10 10:35:12 +08003235 hard_reboot_mode = check_hard_reboot_mode();
3236 if (reboot_mode == RECOVERY_MODE ||
3237 hard_reboot_mode == RECOVERY_HARD_RESET_MODE) {
Ajay Dudani77421292010-10-27 19:34:06 -07003238 boot_into_recovery = 1;
lijuang72875802015-02-10 10:35:12 +08003239 } else if(reboot_mode == FASTBOOT_MODE ||
3240 hard_reboot_mode == FASTBOOT_HARD_RESET_MODE) {
Pavel Nedev5d91d412013-04-29 11:34:24 +03003241 boot_into_fastboot = true;
lijuang72875802015-02-10 10:35:12 +08003242 } else if(reboot_mode == ALARM_BOOT ||
3243 hard_reboot_mode == RTC_HARD_RESET_MODE) {
Matthew Qind886f3c2014-01-17 16:52:01 +08003244 boot_reason_alarm = true;
Ajay Dudani77421292010-10-27 19:34:06 -07003245 }
3246
Matthew Qindefd5562014-07-11 18:02:40 +08003247normal_boot:
Pavel Nedev5d91d412013-04-29 11:34:24 +03003248 if (!boot_into_fastboot)
Shashank Mittald8c42bf2010-06-09 15:44:28 -07003249 {
Pavel Nedev5d91d412013-04-29 11:34:24 +03003250 if (target_is_emmc_boot())
Shashank Mittala0032282011-08-26 14:50:11 -07003251 {
Pavel Nedev5d91d412013-04-29 11:34:24 +03003252 if(emmc_recovery_init())
3253 dprintf(ALWAYS,"error in emmc_recovery_init\n");
3254 if(target_use_signed_kernel())
Shashank Mittala0032282011-08-26 14:50:11 -07003255 {
Pavel Nedev5d91d412013-04-29 11:34:24 +03003256 if((device.is_unlocked) || (device.is_tampered))
3257 {
3258 #ifdef TZ_TAMPER_FUSE
3259 set_tamper_fuse_cmd();
3260 #endif
3261 #if USE_PCOM_SECBOOT
3262 set_tamper_flag(device.is_tampered);
3263 #endif
3264 }
Shashank Mittala0032282011-08-26 14:50:11 -07003265 }
Amit Blay6281ebc2015-01-11 14:44:08 +02003266
Pavel Nedev5d91d412013-04-29 11:34:24 +03003267 boot_linux_from_mmc();
Shashank Mittala0032282011-08-26 14:50:11 -07003268 }
Pavel Nedev5d91d412013-04-29 11:34:24 +03003269 else
3270 {
3271 recovery_init();
3272 #if USE_PCOM_SECBOOT
3273 if((device.is_unlocked) || (device.is_tampered))
3274 set_tamper_flag(device.is_tampered);
3275 #endif
3276 boot_linux_from_flash();
3277 }
3278 dprintf(CRITICAL, "ERROR: Could not do normal boot. Reverting "
3279 "to fastboot mode.\n");
Shashank Mittald8c42bf2010-06-09 15:44:28 -07003280 }
Chandan Uddaraju2943fd62010-06-21 10:56:39 -07003281
Amol Jadi5edf3552013-07-23 14:15:34 -07003282 /* We are here means regular boot did not happen. Start fastboot. */
Channagoud Kadabi4c4884e2013-04-09 17:12:13 -07003283
Amol Jadi5edf3552013-07-23 14:15:34 -07003284 /* register aboot specific fastboot commands */
3285 aboot_fastboot_register_commands();
Amol Jadi57abe4c2011-05-24 15:47:27 -07003286
Amol Jadi5edf3552013-07-23 14:15:34 -07003287 /* dump partition table for debug info */
Kinson Chikf1a43512011-07-14 11:28:39 -07003288 partition_dump();
Amol Jadi5edf3552013-07-23 14:15:34 -07003289
3290 /* initialize and start fastboot */
3291 fastboot_init(target_get_scratch_address(), target_get_max_flash_size());
Brian Swetland9c4c0752009-01-25 16:23:50 -08003292}
3293
Deepa Dinamani41fa8d62013-05-23 13:25:36 -07003294uint32_t get_page_size()
3295{
3296 return page_size;
3297}
3298
Amir Samuelov57a6fa22013-06-05 16:36:43 +03003299/*
3300 * Calculated and save hash (SHA256) for non-signed boot image.
3301 *
Channagoud Kadabi82cf5c62014-08-24 22:17:34 -07003302 * @param image_addr - Boot image address
3303 * @param image_size - Size of the boot image
Amir Samuelov57a6fa22013-06-05 16:36:43 +03003304 *
3305 * @return int - 0 on success, negative value on failure.
3306 */
Channagoud Kadabi82cf5c62014-08-24 22:17:34 -07003307static int aboot_save_boot_hash_mmc(uint32_t image_addr, uint32_t image_size)
Amir Samuelov57a6fa22013-06-05 16:36:43 +03003308{
Channagoud Kadabi82cf5c62014-08-24 22:17:34 -07003309 unsigned int digest[8];
3310#if IMAGE_VERIF_ALGO_SHA1
3311 uint32_t auth_algo = CRYPTO_AUTH_ALG_SHA1;
3312#else
3313 uint32_t auth_algo = CRYPTO_AUTH_ALG_SHA256;
3314#endif
Amir Samuelov57a6fa22013-06-05 16:36:43 +03003315
Channagoud Kadabi82cf5c62014-08-24 22:17:34 -07003316 target_crypto_init_params();
Veera Sundaram Sankaranf9915462014-12-09 11:54:59 -08003317 hash_find((unsigned char *) image_addr, image_size, (unsigned char *)&digest, auth_algo);
Amir Samuelov57a6fa22013-06-05 16:36:43 +03003318
3319 save_kernel_hash_cmd(digest);
Channagoud Kadabi82cf5c62014-08-24 22:17:34 -07003320 dprintf(INFO, "aboot_save_boot_hash_mmc: imagesize_actual size %d bytes.\n", (int) image_size);
Amir Samuelov57a6fa22013-06-05 16:36:43 +03003321
3322 return 0;
3323}
3324
Brian Swetland9c4c0752009-01-25 16:23:50 -08003325APP_START(aboot)
3326 .init = aboot_init,
3327APP_END