blob: 81c8904f8f75aacb9ef16bd6bacd23fe4c77a1c1 [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
Channagoud Kadabi90869ce2015-04-27 11:15:14 -070066#if ENABLE_WBC
67#include <pm_app_smbchg.h>
68#endif
69
Neeti Desai17379b82012-06-04 18:42:53 -070070#if DEVICE_TREE
71#include <libfdt.h>
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -070072#include <dev_tree.h>
Neeti Desai17379b82012-06-04 18:42:53 -070073#endif
74
Aparna Mallavarapu118ccae2015-06-03 13:47:11 +053075#if WDOG_SUPPORT
76#include <wdog.h>
77#endif
78
Shashank Mittalcd98d472011-08-02 14:29:24 -070079#include "image_verify.h"
Shashank Mittal024c0332010-02-03 11:44:00 -080080#include "recovery.h"
Brian Swetland9c4c0752009-01-25 16:23:50 -080081#include "bootimg.h"
82#include "fastboot.h"
Ajay Dudani5c761132011-04-07 20:19:04 -070083#include "sparse_format.h"
Ajay Dudanide984792015-03-02 09:57:41 -080084#include "meta_format.h"
Greg Grisco6e754772011-06-23 12:19:39 -070085#include "mmc.h"
Shashank Mittal162244e2011-08-08 19:01:25 -070086#include "devinfo.h"
Neeti Desai465491e2012-07-31 12:53:35 -070087#include "board.h"
Shashank Mittal162244e2011-08-08 19:01:25 -070088#include "scm.h"
Amit Blay6281ebc2015-01-11 14:44:08 +020089#include "mdtp.h"
kchik@codeaurora.orgbce18ea2011-04-18 20:22:28 -070090
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -070091extern bool target_use_signed_kernel(void);
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -070092extern void platform_uninit(void);
Channagoud Kadabi33defe22013-06-18 18:35:40 -070093extern void target_uninit(void);
Joonwoo Park61112782013-10-02 19:50:39 -070094extern int get_target_boot_params(const char *cmdline, const char *part,
95 char *buf, int buflen);
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -070096
Sridhar Parasuram7e16d172015-07-05 11:35:23 -070097void *info_buf;
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -070098void write_device_info_mmc(device_info *dev);
99void write_device_info_flash(device_info *dev);
Channagoud Kadabi82cf5c62014-08-24 22:17:34 -0700100static int aboot_save_boot_hash_mmc(uint32_t image_addr, uint32_t image_size);
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -0700101
Sridhar Parasurame94e8152014-10-24 14:06:03 -0700102/* fastboot command function pointer */
103typedef void (*fastboot_cmd_fn) (const char *, void *, unsigned);
104
105struct fastboot_cmd_desc {
106 char * name;
107 fastboot_cmd_fn cb;
108};
109
Subbaraman Narayanamurthyeb92bcc2010-07-20 14:32:46 -0700110#define EXPAND(NAME) #NAME
111#define TARGET(NAME) EXPAND(NAME)
Brian Swetland2defe162009-08-18 14:35:59 -0700112
Ajay Dudanicd01f9b2010-02-23 21:13:04 -0800113#ifdef MEMBASE
114#define EMMC_BOOT_IMG_HEADER_ADDR (0xFF000+(MEMBASE))
115#else
David Ng183a7422009-12-07 14:55:21 -0800116#define EMMC_BOOT_IMG_HEADER_ADDR 0xFF000
Ajay Dudanicd01f9b2010-02-23 21:13:04 -0800117#endif
118
Deepa Dinamani0e163a42013-05-24 17:08:15 -0700119#ifndef MEMSIZE
120#define MEMSIZE 1024*1024
121#endif
122
123#define MAX_TAGS_SIZE 1024
124
lijuang72875802015-02-10 10:35:12 +0800125#define RECOVERY_HARD_RESET_MODE 0x01
126#define FASTBOOT_HARD_RESET_MODE 0x02
127#define RTC_HARD_RESET_MODE 0x03
128
Chandan Uddarajude85d3f2010-01-05 16:32:33 -0800129#define RECOVERY_MODE 0x77665502
130#define FASTBOOT_MODE 0x77665500
Matthew Qind886f3c2014-01-17 16:52:01 +0800131#define ALARM_BOOT 0x77665503
Chandan Uddarajude85d3f2010-01-05 16:32:33 -0800132
Kun Liang2f1601a2013-08-12 16:29:54 +0800133/* make 4096 as default size to ensure EFS,EXT4's erasing */
134#define DEFAULT_ERASE_SIZE 4096
Kuogee Hsieh55e92c52013-12-20 08:34:10 -0800135#define MAX_PANEL_BUF_SIZE 128
Kun Liang2f1601a2013-08-12 16:29:54 +0800136
Dhaval Patelf83d73b2014-06-23 16:24:37 -0700137#define DISPLAY_DEFAULT_PREFIX "mdss_mdp"
Sundarajan Srinivasane52065a2014-03-20 16:25:59 -0700138#define BOOT_DEV_MAX_LEN 64
Sundarajan Srinivasan595b71e2013-11-05 12:44:34 -0800139
Abhimanyu Kapur0f79d572014-02-19 22:03:02 -0800140#define IS_ARM64(ptr) (ptr->magic_64 == KERNEL64_HDR_MAGIC) ? true : false
141
Channagoud Kadabifc3b31f2014-06-18 17:41:01 -0700142#define ADD_OF(a, b) (UINT_MAX - b > a) ? (a + b) : UINT_MAX
143
Sridhar Parasuram7bd4aaf2015-02-12 11:14:38 -0800144#if USE_BOOTDEV_CMDLINE
Sundarajan Srinivasane52065a2014-03-20 16:25:59 -0700145static const char *emmc_cmdline = " androidboot.bootdevice=";
Sundarajan Srinivasan3827a102013-09-10 13:57:40 -0700146#else
David Ng183a7422009-12-07 14:55:21 -0800147static const char *emmc_cmdline = " androidboot.emmc=true";
Sundarajan Srinivasan3827a102013-09-10 13:57:40 -0700148#endif
Subbaraman Narayanamurthyf17b4ae2011-02-16 20:19:56 -0800149static const char *usb_sn_cmdline = " androidboot.serialno=";
Pavel Nedev328ac822013-04-05 15:25:11 +0300150static const char *androidboot_mode = " androidboot.mode=";
Matthew Qind886f3c2014-01-17 16:52:01 +0800151static const char *alarmboot_cmdline = " androidboot.alarmboot=true";
Pavel Nedev898298c2013-02-27 12:36:09 -0800152static const char *loglevel = " quiet";
Ajay Dudanica3a33c2011-11-18 08:31:40 -0800153static const char *battchg_pause = " androidboot.mode=charger";
Shashank Mittalcd98d472011-08-02 14:29:24 -0700154static const char *auth_kernel = " androidboot.authorized_kernel=true";
Pavel Nedev5614d222013-06-17 18:01:02 +0300155static const char *secondary_gpt_enable = " gpt";
Shay Nachmanibc10dfe2015-02-10 14:45:55 +0200156static const char *mdtp_activated_flag = " mdtp";
David Ng183a7422009-12-07 14:55:21 -0800157
Ajay Dudani6cff85e2011-02-04 16:02:16 -0800158static const char *baseband_apq = " androidboot.baseband=apq";
159static const char *baseband_msm = " androidboot.baseband=msm";
160static const char *baseband_csfb = " androidboot.baseband=csfb";
161static const char *baseband_svlte2a = " androidboot.baseband=svlte2a";
Ajay Dudani403bc492011-09-30 16:17:21 -0700162static const char *baseband_mdm = " androidboot.baseband=mdm";
Sundarajan Srinivasanaaa8aff2013-11-12 17:19:14 -0800163static const char *baseband_mdm2 = " androidboot.baseband=mdm2";
Amol Jadi5c61a952012-05-04 17:05:35 -0700164static const char *baseband_sglte = " androidboot.baseband=sglte";
Amol Jadi2a15a272013-01-22 12:03:36 -0800165static const char *baseband_dsda = " androidboot.baseband=dsda";
166static const char *baseband_dsda2 = " androidboot.baseband=dsda2";
sundarajan srinivasanf8e9f3f2013-03-04 15:56:58 -0800167static const char *baseband_sglte2 = " androidboot.baseband=sglte2";
Hanumant Singh8e1ac232014-01-29 13:41:51 -0800168static const char *warmboot_cmdline = " qpnp-power-on.warm_boot=1";
Ajay Dudanid04110c2011-01-17 23:55:07 -0800169
Deepa Dinamani41fa8d62013-05-23 13:25:36 -0700170static unsigned page_size = 0;
171static unsigned page_mask = 0;
172static char ffbm_mode_string[FFBM_MODE_BUF_SIZE];
173static bool boot_into_ffbm;
Joonwoo Park61112782013-10-02 19:50:39 -0700174static char target_boot_params[64];
Matthew Qind886f3c2014-01-17 16:52:01 +0800175static bool boot_reason_alarm;
Channagoud Kadabi80a182b2015-03-11 17:04:23 -0700176static bool devinfo_present = true;
Deepa Dinamani41fa8d62013-05-23 13:25:36 -0700177
Shashank Mittalcd98d472011-08-02 14:29:24 -0700178/* Assuming unauthorized kernel image by default */
179static int auth_kernel_img = 0;
180
Channagoud Kadabiaafbbfc2015-03-04 17:52:56 -0800181static device_info device = {DEVICE_MAGIC, 0, 0, 0, 0, {0}, {0},{0}};
vijay kumarc65876c2015-04-24 13:29:16 +0530182static bool is_allow_unlock = 0;
Shashank Mittal162244e2011-08-08 19:01:25 -0700183
Dima Zavin42168f22009-01-30 11:52:22 -0800184struct atag_ptbl_entry
185{
186 char name[16];
187 unsigned offset;
188 unsigned size;
189 unsigned flags;
190};
191
Channagoud Kadabi4c4884e2013-04-09 17:12:13 -0700192/*
193 * Partition info, required to be published
194 * for fastboot
195 */
196struct getvar_partition_info {
197 const char part_name[MAX_GPT_NAME_SIZE]; /* Partition name */
198 char getvar_size[MAX_GET_VAR_NAME_SIZE]; /* fastboot get var name for size */
199 char getvar_type[MAX_GET_VAR_NAME_SIZE]; /* fastboot get var name for type */
200 char size_response[MAX_RSP_SIZE]; /* fastboot response for size */
201 char type_response[MAX_RSP_SIZE]; /* fastboot response for type */
202};
203
204/*
205 * Right now, we are publishing the info for only
206 * three partitions
207 */
208struct getvar_partition_info part_info[] =
209{
210 { "system" , "partition-size:", "partition-type:", "", "ext4" },
211 { "userdata", "partition-size:", "partition-type:", "", "ext4" },
212 { "cache" , "partition-size:", "partition-type:", "", "ext4" },
213};
214
215char max_download_size[MAX_RSP_SIZE];
Ameya Thakur11cf1a62013-08-05 12:44:48 -0700216char charger_screen_enabled[MAX_RSP_SIZE];
Subbaraman Narayanamurthyf17b4ae2011-02-16 20:19:56 -0800217char sn_buf[13];
Dhaval Patel223ec952013-07-18 14:49:44 -0700218char display_panel_buf[MAX_PANEL_BUF_SIZE];
Unnati Gandhi62c8ab82014-01-24 11:01:01 +0530219char panel_display_mode[MAX_RSP_SIZE];
Greg Griscod6250552011-06-29 14:40:23 -0700220
Greg Griscod2471ef2011-07-14 13:00:42 -0700221extern int emmc_recovery_init(void);
222
Kinson Chik0b1c8162011-08-31 16:31:57 -0700223#if NO_KEYPAD_DRIVER
224extern int fastboot_trigger(void);
225#endif
Greg Griscod2471ef2011-07-14 13:00:42 -0700226
Abhimanyu Kapur0f79d572014-02-19 22:03:02 -0800227static void update_ker_tags_rdisk_addr(struct boot_img_hdr *hdr, bool is_arm64)
Channagoud Kadabia22144f2013-03-20 11:49:01 -0700228{
229 /* overwrite the destination of specified for the project */
Channagoud Kadabi7042fa32013-04-26 16:44:14 -0700230#ifdef ABOOT_IGNORE_BOOT_HEADER_ADDRS
Abhimanyu Kapur0f79d572014-02-19 22:03:02 -0800231 if (is_arm64)
232 hdr->kernel_addr = ABOOT_FORCE_KERNEL64_ADDR;
233 else
234 hdr->kernel_addr = ABOOT_FORCE_KERNEL_ADDR;
Channagoud Kadabi7042fa32013-04-26 16:44:14 -0700235 hdr->ramdisk_addr = ABOOT_FORCE_RAMDISK_ADDR;
236 hdr->tags_addr = ABOOT_FORCE_TAGS_ADDR;
Channagoud Kadabia22144f2013-03-20 11:49:01 -0700237#endif
238}
239
Dima Zavin42168f22009-01-30 11:52:22 -0800240static void ptentry_to_tag(unsigned **ptr, struct ptentry *ptn)
241{
242 struct atag_ptbl_entry atag_ptn;
243
244 memcpy(atag_ptn.name, ptn->name, 16);
245 atag_ptn.name[15] = '\0';
246 atag_ptn.offset = ptn->start;
247 atag_ptn.size = ptn->length;
248 atag_ptn.flags = ptn->flags;
249 memcpy(*ptr, &atag_ptn, sizeof(struct atag_ptbl_entry));
250 *ptr += sizeof(struct atag_ptbl_entry) / sizeof(unsigned);
251}
Brian Swetland9c4c0752009-01-25 16:23:50 -0800252
Neeti Desaie245d492012-06-01 12:52:13 -0700253unsigned char *update_cmdline(const char * cmdline)
Brian Swetland9c4c0752009-01-25 16:23:50 -0800254{
David Ng183a7422009-12-07 14:55:21 -0800255 int cmdline_len = 0;
256 int have_cmdline = 0;
Amol Jadi168b7712012-03-06 16:15:00 -0800257 unsigned char *cmdline_final = NULL;
Neeti Desaie245d492012-06-01 12:52:13 -0700258 int pause_at_bootup = 0;
Hanumant Singh8e1ac232014-01-29 13:41:51 -0800259 bool warm_boot = false;
Pavel Nedev5614d222013-06-17 18:01:02 +0300260 bool gpt_exists = partition_gpt_exists();
Joonwoo Park61112782013-10-02 19:50:39 -0700261 int have_target_boot_params = 0;
Sundarajan Srinivasane52065a2014-03-20 16:25:59 -0700262 char *boot_dev_buf = NULL;
Shay Nachmanibc10dfe2015-02-10 14:45:55 +0200263 bool is_mdtp_activated = 0;
264#ifdef MDTP_SUPPORT
265 mdtp_activated(&is_mdtp_activated);
266#endif /* MDTP_SUPPORT */
Dima Zavin42168f22009-01-30 11:52:22 -0800267
Brian Swetland9c4c0752009-01-25 16:23:50 -0800268 if (cmdline && cmdline[0]) {
David Ng183a7422009-12-07 14:55:21 -0800269 cmdline_len = strlen(cmdline);
270 have_cmdline = 1;
271 }
272 if (target_is_emmc_boot()) {
273 cmdline_len += strlen(emmc_cmdline);
Sridhar Parasuram7bd4aaf2015-02-12 11:14:38 -0800274#if USE_BOOTDEV_CMDLINE
Sundarajan Srinivasane52065a2014-03-20 16:25:59 -0700275 boot_dev_buf = (char *) malloc(sizeof(char) * BOOT_DEV_MAX_LEN);
276 ASSERT(boot_dev_buf);
277 platform_boot_dev_cmdline(boot_dev_buf);
278 cmdline_len += strlen(boot_dev_buf);
Sundarajan Srinivasan3827a102013-09-10 13:57:40 -0700279#endif
David Ng183a7422009-12-07 14:55:21 -0800280 }
Subbaraman Narayanamurthyf17b4ae2011-02-16 20:19:56 -0800281
282 cmdline_len += strlen(usb_sn_cmdline);
283 cmdline_len += strlen(sn_buf);
284
Pavel Nedev5614d222013-06-17 18:01:02 +0300285 if (boot_into_recovery && gpt_exists)
286 cmdline_len += strlen(secondary_gpt_enable);
287
Shay Nachmanibc10dfe2015-02-10 14:45:55 +0200288 if(is_mdtp_activated)
289 cmdline_len += strlen(mdtp_activated_flag);
290
Pavel Nedev328ac822013-04-05 15:25:11 +0300291 if (boot_into_ffbm) {
292 cmdline_len += strlen(androidboot_mode);
Deepa Dinamani41fa8d62013-05-23 13:25:36 -0700293 cmdline_len += strlen(ffbm_mode_string);
Pavel Nedev898298c2013-02-27 12:36:09 -0800294 /* reduce kernel console messages to speed-up boot */
295 cmdline_len += strlen(loglevel);
Matthew Qind886f3c2014-01-17 16:52:01 +0800296 } else if (boot_reason_alarm) {
297 cmdline_len += strlen(alarmboot_cmdline);
Zhenhua Huang431dafa2015-06-30 16:13:37 +0800298 } else if ((target_build_variant_user() || device.charger_screen_enabled)
299 && target_pause_for_battery_charge()) {
David Ngf773dde2010-07-26 19:55:08 -0700300 pause_at_bootup = 1;
301 cmdline_len += strlen(battchg_pause);
302 }
Ajay Dudanid04110c2011-01-17 23:55:07 -0800303
Shashank Mittalcd98d472011-08-02 14:29:24 -0700304 if(target_use_signed_kernel() && auth_kernel_img) {
305 cmdline_len += strlen(auth_kernel);
306 }
307
Joonwoo Park61112782013-10-02 19:50:39 -0700308 if (get_target_boot_params(cmdline, boot_into_recovery ? "recoveryfs" :
309 "system",
310 target_boot_params,
311 sizeof(target_boot_params)) == 0) {
312 have_target_boot_params = 1;
313 cmdline_len += strlen(target_boot_params);
314 }
315
Ajay Dudanid04110c2011-01-17 23:55:07 -0800316 /* Determine correct androidboot.baseband to use */
317 switch(target_baseband())
318 {
319 case BASEBAND_APQ:
320 cmdline_len += strlen(baseband_apq);
321 break;
322
323 case BASEBAND_MSM:
324 cmdline_len += strlen(baseband_msm);
325 break;
326
327 case BASEBAND_CSFB:
328 cmdline_len += strlen(baseband_csfb);
329 break;
330
Ajay Dudani6cff85e2011-02-04 16:02:16 -0800331 case BASEBAND_SVLTE2A:
332 cmdline_len += strlen(baseband_svlte2a);
Ajay Dudanid04110c2011-01-17 23:55:07 -0800333 break;
Ajay Dudani403bc492011-09-30 16:17:21 -0700334
335 case BASEBAND_MDM:
336 cmdline_len += strlen(baseband_mdm);
337 break;
Amol Jadi5c61a952012-05-04 17:05:35 -0700338
Sundarajan Srinivasanaaa8aff2013-11-12 17:19:14 -0800339 case BASEBAND_MDM2:
340 cmdline_len += strlen(baseband_mdm2);
341 break;
342
Amol Jadi5c61a952012-05-04 17:05:35 -0700343 case BASEBAND_SGLTE:
344 cmdline_len += strlen(baseband_sglte);
345 break;
Channagoud Kadabi141f2982012-10-31 11:23:02 +0530346
sundarajan srinivasanf8e9f3f2013-03-04 15:56:58 -0800347 case BASEBAND_SGLTE2:
348 cmdline_len += strlen(baseband_sglte2);
349 break;
350
Channagoud Kadabi141f2982012-10-31 11:23:02 +0530351 case BASEBAND_DSDA:
352 cmdline_len += strlen(baseband_dsda);
353 break;
Amol Jadi2a15a272013-01-22 12:03:36 -0800354
355 case BASEBAND_DSDA2:
356 cmdline_len += strlen(baseband_dsda2);
357 break;
Ajay Dudanid04110c2011-01-17 23:55:07 -0800358 }
359
Lijuan Gao4a5b8322014-07-24 10:38:42 +0800360 if (cmdline) {
361 if ((strstr(cmdline, DISPLAY_DEFAULT_PREFIX) == NULL) &&
Padmanabhan Komandurubccbcdc2015-06-30 16:19:24 +0530362 target_display_panel_node(display_panel_buf,
363 MAX_PANEL_BUF_SIZE) &&
Lijuan Gao4a5b8322014-07-24 10:38:42 +0800364 strlen(display_panel_buf)) {
365 cmdline_len += strlen(display_panel_buf);
366 }
Dhaval Patel223ec952013-07-18 14:49:44 -0700367 }
368
Hanumant Singh8e1ac232014-01-29 13:41:51 -0800369 if (target_warm_boot()) {
370 warm_boot = true;
371 cmdline_len += strlen(warmboot_cmdline);
372 }
373
David Ng183a7422009-12-07 14:55:21 -0800374 if (cmdline_len > 0) {
375 const char *src;
Maria Yu52254c02014-07-04 16:14:54 +0800376 unsigned char *dst;
377
378 cmdline_final = (unsigned char*) malloc((cmdline_len + 4) & (~3));
379 ASSERT(cmdline_final != NULL);
380 dst = cmdline_final;
Neeti Desaie245d492012-06-01 12:52:13 -0700381
Amol Jadi168b7712012-03-06 16:15:00 -0800382 /* Save start ptr for debug print */
David Ng183a7422009-12-07 14:55:21 -0800383 if (have_cmdline) {
384 src = cmdline;
385 while ((*dst++ = *src++));
386 }
387 if (target_is_emmc_boot()) {
388 src = emmc_cmdline;
389 if (have_cmdline) --dst;
David Ngf773dde2010-07-26 19:55:08 -0700390 have_cmdline = 1;
391 while ((*dst++ = *src++));
Sridhar Parasuram7bd4aaf2015-02-12 11:14:38 -0800392#if USE_BOOTDEV_CMDLINE
Sundarajan Srinivasane52065a2014-03-20 16:25:59 -0700393 src = boot_dev_buf;
394 if (have_cmdline) --dst;
395 while ((*dst++ = *src++));
396#endif
David Ngf773dde2010-07-26 19:55:08 -0700397 }
Subbaraman Narayanamurthyf17b4ae2011-02-16 20:19:56 -0800398
399 src = usb_sn_cmdline;
400 if (have_cmdline) --dst;
401 have_cmdline = 1;
402 while ((*dst++ = *src++));
403 src = sn_buf;
404 if (have_cmdline) --dst;
405 have_cmdline = 1;
406 while ((*dst++ = *src++));
Hanumant Singh8e1ac232014-01-29 13:41:51 -0800407 if (warm_boot) {
408 if (have_cmdline) --dst;
409 src = warmboot_cmdline;
410 while ((*dst++ = *src++));
411 }
Subbaraman Narayanamurthyf17b4ae2011-02-16 20:19:56 -0800412
Pavel Nedev5614d222013-06-17 18:01:02 +0300413 if (boot_into_recovery && gpt_exists) {
414 src = secondary_gpt_enable;
415 if (have_cmdline) --dst;
416 while ((*dst++ = *src++));
417 }
418
Shay Nachmanibc10dfe2015-02-10 14:45:55 +0200419 if (is_mdtp_activated) {
420 src = mdtp_activated_flag;
421 if (have_cmdline) --dst;
422 while ((*dst++ = *src++));
423 }
424
Pavel Nedev328ac822013-04-05 15:25:11 +0300425 if (boot_into_ffbm) {
426 src = androidboot_mode;
427 if (have_cmdline) --dst;
428 while ((*dst++ = *src++));
Deepa Dinamani41fa8d62013-05-23 13:25:36 -0700429 src = ffbm_mode_string;
Pavel Nedev328ac822013-04-05 15:25:11 +0300430 if (have_cmdline) --dst;
431 while ((*dst++ = *src++));
Pavel Nedev898298c2013-02-27 12:36:09 -0800432 src = loglevel;
433 if (have_cmdline) --dst;
434 while ((*dst++ = *src++));
Matthew Qind886f3c2014-01-17 16:52:01 +0800435 } else if (boot_reason_alarm) {
436 src = alarmboot_cmdline;
437 if (have_cmdline) --dst;
438 while ((*dst++ = *src++));
Pavel Nedev328ac822013-04-05 15:25:11 +0300439 } else if (pause_at_bootup) {
David Ngf773dde2010-07-26 19:55:08 -0700440 src = battchg_pause;
441 if (have_cmdline) --dst;
David Ng183a7422009-12-07 14:55:21 -0800442 while ((*dst++ = *src++));
443 }
Ajay Dudanid04110c2011-01-17 23:55:07 -0800444
Shashank Mittalcd98d472011-08-02 14:29:24 -0700445 if(target_use_signed_kernel() && auth_kernel_img) {
446 src = auth_kernel;
447 if (have_cmdline) --dst;
448 while ((*dst++ = *src++));
449 }
450
Ajay Dudanid04110c2011-01-17 23:55:07 -0800451 switch(target_baseband())
452 {
453 case BASEBAND_APQ:
454 src = baseband_apq;
455 if (have_cmdline) --dst;
456 while ((*dst++ = *src++));
457 break;
458
459 case BASEBAND_MSM:
460 src = baseband_msm;
461 if (have_cmdline) --dst;
462 while ((*dst++ = *src++));
463 break;
464
465 case BASEBAND_CSFB:
466 src = baseband_csfb;
467 if (have_cmdline) --dst;
468 while ((*dst++ = *src++));
469 break;
470
Ajay Dudani6cff85e2011-02-04 16:02:16 -0800471 case BASEBAND_SVLTE2A:
472 src = baseband_svlte2a;
Ajay Dudanid04110c2011-01-17 23:55:07 -0800473 if (have_cmdline) --dst;
474 while ((*dst++ = *src++));
475 break;
Ajay Dudani403bc492011-09-30 16:17:21 -0700476
477 case BASEBAND_MDM:
478 src = baseband_mdm;
479 if (have_cmdline) --dst;
480 while ((*dst++ = *src++));
481 break;
Amol Jadi5c61a952012-05-04 17:05:35 -0700482
Sundarajan Srinivasanaaa8aff2013-11-12 17:19:14 -0800483 case BASEBAND_MDM2:
484 src = baseband_mdm2;
485 if (have_cmdline) --dst;
486 while ((*dst++ = *src++));
487 break;
488
Amol Jadi5c61a952012-05-04 17:05:35 -0700489 case BASEBAND_SGLTE:
490 src = baseband_sglte;
491 if (have_cmdline) --dst;
492 while ((*dst++ = *src++));
493 break;
Channagoud Kadabi141f2982012-10-31 11:23:02 +0530494
sundarajan srinivasanf8e9f3f2013-03-04 15:56:58 -0800495 case BASEBAND_SGLTE2:
496 src = baseband_sglte2;
497 if (have_cmdline) --dst;
498 while ((*dst++ = *src++));
499 break;
500
Channagoud Kadabi141f2982012-10-31 11:23:02 +0530501 case BASEBAND_DSDA:
502 src = baseband_dsda;
503 if (have_cmdline) --dst;
504 while ((*dst++ = *src++));
505 break;
Amol Jadi2a15a272013-01-22 12:03:36 -0800506
507 case BASEBAND_DSDA2:
508 src = baseband_dsda2;
509 if (have_cmdline) --dst;
510 while ((*dst++ = *src++));
511 break;
Ajay Dudanid04110c2011-01-17 23:55:07 -0800512 }
Dhaval Patel223ec952013-07-18 14:49:44 -0700513
514 if (strlen(display_panel_buf)) {
Dhaval Patel223ec952013-07-18 14:49:44 -0700515 src = display_panel_buf;
516 if (have_cmdline) --dst;
517 while ((*dst++ = *src++));
518 }
Joonwoo Park61112782013-10-02 19:50:39 -0700519
520 if (have_target_boot_params) {
521 if (have_cmdline) --dst;
522 src = target_boot_params;
523 while ((*dst++ = *src++));
524 }
Neeti Desaie245d492012-06-01 12:52:13 -0700525 }
Dhaval Patel223ec952013-07-18 14:49:44 -0700526
527
Sundarajan Srinivasane52065a2014-03-20 16:25:59 -0700528 if (boot_dev_buf)
529 free(boot_dev_buf);
530
Veera Sundaram Sankaranf9915462014-12-09 11:54:59 -0800531 if (cmdline_final)
532 dprintf(INFO, "cmdline: %s\n", cmdline_final);
533 else
534 dprintf(INFO, "cmdline is NULL\n");
Neeti Desaie245d492012-06-01 12:52:13 -0700535 return cmdline_final;
536}
537
538unsigned *atag_core(unsigned *ptr)
539{
540 /* CORE */
541 *ptr++ = 2;
542 *ptr++ = 0x54410001;
543
544 return ptr;
545
546}
547
548unsigned *atag_ramdisk(unsigned *ptr, void *ramdisk,
549 unsigned ramdisk_size)
550{
551 if (ramdisk_size) {
552 *ptr++ = 4;
553 *ptr++ = 0x54420005;
554 *ptr++ = (unsigned)ramdisk;
555 *ptr++ = ramdisk_size;
Brian Swetland9c4c0752009-01-25 16:23:50 -0800556 }
557
Neeti Desaie245d492012-06-01 12:52:13 -0700558 return ptr;
559}
560
561unsigned *atag_ptable(unsigned **ptr_addr)
562{
563 int i;
564 struct ptable *ptable;
565
566 if ((ptable = flash_get_ptable()) && (ptable->count != 0)) {
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -0700567 *(*ptr_addr)++ = 2 + (ptable->count * (sizeof(struct atag_ptbl_entry) /
568 sizeof(unsigned)));
Neeti Desaie245d492012-06-01 12:52:13 -0700569 *(*ptr_addr)++ = 0x4d534d70;
570 for (i = 0; i < ptable->count; ++i)
571 ptentry_to_tag(ptr_addr, ptable_get(ptable, i));
572 }
573
574 return (*ptr_addr);
575}
576
577unsigned *atag_cmdline(unsigned *ptr, const char *cmdline)
578{
579 int cmdline_length = 0;
580 int n;
Neeti Desaie245d492012-06-01 12:52:13 -0700581 char *dest;
582
Amol Jadi10c7d1c2013-01-25 13:24:29 -0800583 cmdline_length = strlen((const char*)cmdline);
Neeti Desaie245d492012-06-01 12:52:13 -0700584 n = (cmdline_length + 4) & (~3);
585
586 *ptr++ = (n / 4) + 2;
587 *ptr++ = 0x54410009;
588 dest = (char *) ptr;
Amol Jadi10c7d1c2013-01-25 13:24:29 -0800589 while ((*dest++ = *cmdline++));
Neeti Desaie245d492012-06-01 12:52:13 -0700590 ptr += (n / 4);
591
592 return ptr;
593}
594
595unsigned *atag_end(unsigned *ptr)
596{
Brian Swetland9c4c0752009-01-25 16:23:50 -0800597 /* END */
598 *ptr++ = 0;
599 *ptr++ = 0;
600
Neeti Desaie245d492012-06-01 12:52:13 -0700601 return ptr;
602}
603
604void generate_atags(unsigned *ptr, const char *cmdline,
605 void *ramdisk, unsigned ramdisk_size)
606{
607
608 ptr = atag_core(ptr);
609 ptr = atag_ramdisk(ptr, ramdisk, ramdisk_size);
610 ptr = target_atag_mem(ptr);
611
612 /* Skip NAND partition ATAGS for eMMC boot */
613 if (!target_is_emmc_boot()){
614 ptr = atag_ptable(&ptr);
615 }
616
617 ptr = atag_cmdline(ptr, cmdline);
618 ptr = atag_end(ptr);
619}
620
Deepa Dinamani0bf2f442012-10-19 11:41:06 -0700621typedef void entry_func_ptr(unsigned, unsigned, unsigned*);
Neeti Desaie245d492012-06-01 12:52:13 -0700622void boot_linux(void *kernel, unsigned *tags,
623 const char *cmdline, unsigned machtype,
624 void *ramdisk, unsigned ramdisk_size)
625{
Amol Jadi10c7d1c2013-01-25 13:24:29 -0800626 unsigned char *final_cmdline;
Amol Jadib6be5c12012-11-14 13:39:51 -0800627#if DEVICE_TREE
Neeti Desai17379b82012-06-04 18:42:53 -0700628 int ret = 0;
Amol Jadib6be5c12012-11-14 13:39:51 -0800629#endif
630
Deepa Dinamani0bf2f442012-10-19 11:41:06 -0700631 void (*entry)(unsigned, unsigned, unsigned*) = (entry_func_ptr*)(PA((addr_t)kernel));
Deepa Dinamani25a9f762012-11-30 15:57:15 -0800632 uint32_t tags_phys = PA((addr_t)tags);
Abhimanyu Kapur0f79d572014-02-19 22:03:02 -0800633 struct kernel64_hdr *kptr = (struct kernel64_hdr*)kernel;
Deepa Dinamani25a9f762012-11-30 15:57:15 -0800634
Unnati Gandhi0c8e7c52014-07-17 14:33:09 +0530635 ramdisk = (void *)PA((addr_t)ramdisk);
Neeti Desaie245d492012-06-01 12:52:13 -0700636
Amol Jadi10c7d1c2013-01-25 13:24:29 -0800637 final_cmdline = update_cmdline((const char*)cmdline);
638
Neeti Desai17379b82012-06-04 18:42:53 -0700639#if DEVICE_TREE
Amol Jadib6be5c12012-11-14 13:39:51 -0800640 dprintf(INFO, "Updating device tree: start\n");
641
Neeti Desai17379b82012-06-04 18:42:53 -0700642 /* Update the Device Tree */
Unnati Gandhi0c8e7c52014-07-17 14:33:09 +0530643 ret = update_device_tree((void *)tags,(const char *)final_cmdline, ramdisk, ramdisk_size);
Neeti Desai17379b82012-06-04 18:42:53 -0700644 if(ret)
645 {
646 dprintf(CRITICAL, "ERROR: Updating Device Tree Failed \n");
647 ASSERT(0);
648 }
Amol Jadib6be5c12012-11-14 13:39:51 -0800649 dprintf(INFO, "Updating device tree: done\n");
Neeti Desai17379b82012-06-04 18:42:53 -0700650#else
Neeti Desaie245d492012-06-01 12:52:13 -0700651 /* Generating the Atags */
Amol Jadi10c7d1c2013-01-25 13:24:29 -0800652 generate_atags(tags, final_cmdline, ramdisk, ramdisk_size);
Neeti Desai17379b82012-06-04 18:42:53 -0700653#endif
Neeti Desaie245d492012-06-01 12:52:13 -0700654
Maria Yu52254c02014-07-04 16:14:54 +0800655 free(final_cmdline);
Channagoud Kadabi5d0371c2014-10-21 22:27:07 -0700656
657#if VERIFIED_BOOT
658 /* Write protect the device info */
Channagoud Kadabi3bd9d1e2015-05-05 16:18:20 -0700659 if (!boot_into_recovery && target_build_variant_user() && devinfo_present && mmc_write_protect("devinfo", 1))
Channagoud Kadabi5d0371c2014-10-21 22:27:07 -0700660 {
661 dprintf(INFO, "Failed to write protect dev info\n");
662 ASSERT(0);
663 }
664#endif
665
Channagoud Kadabi33defe22013-06-18 18:35:40 -0700666 /* Perform target specific cleanup */
667 target_uninit();
668
Aravind Venkateswaran8f076242014-02-25 16:25:30 -0800669 /* Turn off splash screen if enabled */
670#if DISPLAY_SPLASH_SCREEN
671 target_display_shutdown();
672#endif
673
674
Deepa Dinamani33734bc2013-03-06 12:16:06 -0800675 dprintf(INFO, "booting linux @ %p, ramdisk @ %p (%d), tags/device tree @ %p\n",
Unnati Gandhi0c8e7c52014-07-17 14:33:09 +0530676 entry, ramdisk, ramdisk_size, (void *)tags_phys);
Brian Swetland9c4c0752009-01-25 16:23:50 -0800677
678 enter_critical_section();
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -0700679
Aparna Mallavarapu118ccae2015-06-03 13:47:11 +0530680 /* Initialise wdog to catch early kernel crashes */
681#if WDOG_SUPPORT
682 msm_wdog_init();
683#endif
Amol Jadi4421e652011-06-16 15:00:48 -0700684 /* do any platform specific cleanup before kernel entry */
685 platform_uninit();
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -0700686
Brian Swetland9c4c0752009-01-25 16:23:50 -0800687 arch_disable_cache(UCACHE);
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -0700688
Amol Jadi504f9fe2012-08-16 13:56:48 -0700689#if ARM_WITH_MMU
Brian Swetland9c4c0752009-01-25 16:23:50 -0800690 arch_disable_mmu();
Amol Jadi504f9fe2012-08-16 13:56:48 -0700691#endif
Amol Jadi492d5a52013-03-15 16:12:34 -0700692 bs_set_timestamp(BS_KERNEL_ENTRY);
Abhimanyu Kapur0f79d572014-02-19 22:03:02 -0800693
694 if (IS_ARM64(kptr))
695 /* Jump to a 64bit kernel */
696 scm_elexec_call((paddr_t)kernel, tags_phys);
697 else
698 /* Jump to a 32bit kernel */
699 entry(0, machtype, (unsigned*)tags_phys);
Brian Swetland9c4c0752009-01-25 16:23:50 -0800700}
701
Deepa Dinamani0e163a42013-05-24 17:08:15 -0700702/* Function to check if the memory address range falls within the aboot
703 * boundaries.
704 * start: Start of the memory region
705 * size: Size of the memory region
706 */
707int check_aboot_addr_range_overlap(uint32_t start, uint32_t size)
708{
709 /* Check for boundary conditions. */
Sundarajan Srinivasance2a0ea2013-12-16 17:02:56 -0800710 if ((UINT_MAX - start) < size)
Deepa Dinamani0e163a42013-05-24 17:08:15 -0700711 return -1;
712
713 /* Check for memory overlap. */
714 if ((start < MEMBASE) && ((start + size) <= MEMBASE))
715 return 0;
Channagoud Kadabi94143912013-10-15 12:53:52 -0700716 else if (start >= (MEMBASE + MEMSIZE))
Deepa Dinamani0e163a42013-05-24 17:08:15 -0700717 return 0;
718 else
719 return -1;
720}
721
Shashank Mittaldcc2e352009-11-19 19:11:16 -0800722#define ROUND_TO_PAGE(x,y) (((x) + (y)) & (~(y)))
Brian Swetland9c4c0752009-01-25 16:23:50 -0800723
Abhimanyu Kapur0f79d572014-02-19 22:03:02 -0800724BUF_DMA_ALIGN(buf, BOOT_IMG_MAX_PAGE_SIZE); //Equal to max-supported pagesize
Amol Jadib6be5c12012-11-14 13:39:51 -0800725#if DEVICE_TREE
Abhimanyu Kapur0f79d572014-02-19 22:03:02 -0800726BUF_DMA_ALIGN(dt_buf, BOOT_IMG_MAX_PAGE_SIZE);
Amol Jadib6be5c12012-11-14 13:39:51 -0800727#endif
Dima Zavin214cc642009-01-26 11:16:21 -0800728
Deepa Dinamani0e163a42013-05-24 17:08:15 -0700729static void verify_signed_bootimg(uint32_t bootimg_addr, uint32_t bootimg_size)
730{
731 int ret;
Channagoud Kadabia8c623f2015-01-13 14:48:48 -0800732
733#if !VERIFIED_BOOT
Sundarajan Srinivasance54d6e2013-11-11 12:45:00 -0800734#if IMAGE_VERIF_ALGO_SHA1
735 uint32_t auth_algo = CRYPTO_AUTH_ALG_SHA1;
736#else
737 uint32_t auth_algo = CRYPTO_AUTH_ALG_SHA256;
738#endif
Channagoud Kadabia8c623f2015-01-13 14:48:48 -0800739#endif
Deepa Dinamani0e163a42013-05-24 17:08:15 -0700740
741 /* Assume device is rooted at this time. */
742 device.is_tampered = 1;
743
744 dprintf(INFO, "Authenticating boot image (%d): start\n", bootimg_size);
745
Shashank Mittald3e54dd2014-08-28 15:24:02 -0700746#if VERIFIED_BOOT
747 if(boot_into_recovery)
748 {
749 ret = boot_verify_image((unsigned char *)bootimg_addr,
Unnati Gandhi47051252015-03-02 15:21:09 +0530750 bootimg_size, "/recovery");
Shashank Mittald3e54dd2014-08-28 15:24:02 -0700751 }
752 else
753 {
754 ret = boot_verify_image((unsigned char *)bootimg_addr,
Unnati Gandhi47051252015-03-02 15:21:09 +0530755 bootimg_size, "/boot");
Shashank Mittald3e54dd2014-08-28 15:24:02 -0700756 }
757 boot_verify_print_state();
758#else
Deepa Dinamani0e163a42013-05-24 17:08:15 -0700759 ret = image_verify((unsigned char *)bootimg_addr,
760 (unsigned char *)(bootimg_addr + bootimg_size),
761 bootimg_size,
Sundarajan Srinivasance54d6e2013-11-11 12:45:00 -0800762 auth_algo);
Shashank Mittald3e54dd2014-08-28 15:24:02 -0700763#endif
Deepa Dinamani0e163a42013-05-24 17:08:15 -0700764 dprintf(INFO, "Authenticating boot image: done return value = %d\n", ret);
765
766 if (ret)
767 {
768 /* Authorized kernel */
769 device.is_tampered = 0;
Sundarajan Srinivasan3fb21f12013-09-16 18:36:15 -0700770 auth_kernel_img = 1;
Deepa Dinamani0e163a42013-05-24 17:08:15 -0700771 }
772
Amit Blay4aa292f2015-04-28 21:55:59 +0300773#ifdef MDTP_SUPPORT
774 {
775 /* Verify MDTP lock.
776 * For boot & recovery partitions, use aboot's verification result.
777 */
778 mdtp_ext_partition_verification_t ext_partition;
779 ext_partition.partition = boot_into_recovery ? MDTP_PARTITION_RECOVERY : MDTP_PARTITION_BOOT;
780 ext_partition.integrity_state = device.is_tampered ? MDTP_PARTITION_STATE_INVALID : MDTP_PARTITION_STATE_VALID;
781 ext_partition.page_size = 0; /* Not needed since already validated */
782 ext_partition.image_addr = 0; /* Not needed since already validated */
783 ext_partition.image_size = 0; /* Not needed since already validated */
784 ext_partition.sig_avail = FALSE; /* Not needed since already validated */
785 mdtp_fwlock_verify_lock(&ext_partition);
786 }
787#endif /* MDTP_SUPPORT */
788
Deepa Dinamani0e163a42013-05-24 17:08:15 -0700789#if USE_PCOM_SECBOOT
790 set_tamper_flag(device.is_tampered);
791#endif
792
Shashank Mittald3e54dd2014-08-28 15:24:02 -0700793#if VERIFIED_BOOT
794 if(boot_verify_get_state() == RED)
795 {
796 if(!boot_into_recovery)
797 {
798 dprintf(CRITICAL,
799 "Device verification failed. Rebooting into recovery.\n");
Unnati Gandhi17b3bfc2015-05-11 12:58:16 +0530800 mdelay(1000);
Shashank Mittald3e54dd2014-08-28 15:24:02 -0700801 reboot_device(RECOVERY_MODE);
802 }
803 else
804 {
805 dprintf(CRITICAL,
806 "Recovery image verification failed. Asserting..\n");
807 ASSERT(0);
808 }
809 }
810#endif
Unnati Gandhi1be04752015-03-27 19:41:53 +0530811
812 if(device.is_tampered)
813 {
814 write_device_info_mmc(&device);
815 #ifdef TZ_TAMPER_FUSE
816 set_tamper_fuse_cmd();
817 #endif
818 #ifdef ASSERT_ON_TAMPER
819 dprintf(CRITICAL, "Device is tampered. Asserting..\n");
820 ASSERT(0);
821 #endif
822 }
823
Deepa Dinamani0e163a42013-05-24 17:08:15 -0700824}
825
Maunik Shah0f3c8ac2014-03-02 17:47:58 +0530826static bool check_format_bit()
827{
828 bool ret = false;
829 int index;
830 uint64_t offset;
831 struct boot_selection_info *in = NULL;
832 char *buf = NULL;
833
834 index = partition_get_index("bootselect");
835 if (index == INVALID_PTN)
836 {
837 dprintf(INFO, "Unable to locate /bootselect partition\n");
838 return ret;
839 }
840 offset = partition_get_offset(index);
841 if(!offset)
842 {
843 dprintf(INFO, "partition /bootselect doesn't exist\n");
844 return ret;
845 }
846 buf = (char *) memalign(CACHE_LINE, ROUNDUP(page_size, CACHE_LINE));
847 ASSERT(buf);
Unnati Gandhi0c8e7c52014-07-17 14:33:09 +0530848 if (mmc_read(offset, (uint32_t *)buf, page_size))
Maunik Shah0f3c8ac2014-03-02 17:47:58 +0530849 {
850 dprintf(INFO, "mmc read failure /bootselect %d\n", page_size);
851 free(buf);
852 return ret;
853 }
854 in = (struct boot_selection_info *) buf;
855 if ((in->signature == BOOTSELECT_SIGNATURE) &&
856 (in->version == BOOTSELECT_VERSION)) {
857 if ((in->state_info & BOOTSELECT_FORMAT) &&
858 !(in->state_info & BOOTSELECT_FACTORY))
859 ret = true;
860 } else {
861 dprintf(CRITICAL, "Signature: 0x%08x or version: 0x%08x mismatched of /bootselect\n",
862 in->signature, in->version);
863 ASSERT(0);
864 }
865 free(buf);
866 return ret;
867}
868
Shashank Mittald3e54dd2014-08-28 15:24:02 -0700869void boot_verifier_init()
870{
Shashank Mittald3e54dd2014-08-28 15:24:02 -0700871 uint32_t boot_state;
872 /* Check if device unlock */
873 if(device.is_unlocked)
874 {
875 boot_verify_send_event(DEV_UNLOCK);
876 boot_verify_print_state();
877 dprintf(CRITICAL, "Device is unlocked! Skipping verification...\n");
878 return;
879 }
880 else
881 {
882 boot_verify_send_event(BOOT_INIT);
883 }
884
885 /* Initialize keystore */
886 boot_state = boot_verify_keystore_init();
887 if(boot_state == YELLOW)
888 {
889 boot_verify_print_state();
890 dprintf(CRITICAL, "Keystore verification failed! Continuing anyways...\n");
891 }
892}
893
Shashank Mittal23b8f422010-04-16 19:27:21 -0700894int boot_linux_from_mmc(void)
895{
896 struct boot_img_hdr *hdr = (void*) buf;
897 struct boot_img_hdr *uhdr;
898 unsigned offset = 0;
Deepa Dinamani41fa8d62013-05-23 13:25:36 -0700899 int rcode;
Shashank Mittal23b8f422010-04-16 19:27:21 -0700900 unsigned long long ptn = 0;
Kinson Chikf1a43512011-07-14 11:28:39 -0700901 int index = INVALID_PTN;
Shashank Mittal23b8f422010-04-16 19:27:21 -0700902
Shashank Mittalcd98d472011-08-02 14:29:24 -0700903 unsigned char *image_addr = 0;
904 unsigned kernel_actual;
905 unsigned ramdisk_actual;
906 unsigned imagesize_actual;
Neeti Desai465491e2012-07-31 12:53:35 -0700907 unsigned second_actual = 0;
Neeti Desai465491e2012-07-31 12:53:35 -0700908
Matthew Qin271927e2015-03-31 22:07:07 -0400909 unsigned int dtb_size = 0;
Matthew Qinbb7923d2015-02-09 10:56:09 +0800910 unsigned int out_len = 0;
911 unsigned int out_avai_len = 0;
912 unsigned char *out_addr = NULL;
913 uint32_t dtb_offset = 0;
914 unsigned char *kernel_start_addr = NULL;
915 unsigned int kernel_size = 0;
916 int rc;
917
Neeti Desai465491e2012-07-31 12:53:35 -0700918#if DEVICE_TREE
919 struct dt_table *table;
Joel Kingaa335dc2013-06-03 16:11:08 -0700920 struct dt_entry dt_entry;
Neeti Desai465491e2012-07-31 12:53:35 -0700921 unsigned dt_table_offset;
Deepa Dinamani7aaf83d2012-12-21 11:27:01 -0800922 uint32_t dt_actual;
Deepa Dinamani19648b42013-09-05 17:05:55 -0700923 uint32_t dt_hdr_size;
Matthew Qin271927e2015-03-31 22:07:07 -0400924 unsigned char *best_match_dt_addr = NULL;
Neeti Desai465491e2012-07-31 12:53:35 -0700925#endif
Matthew Qin49e51fa2015-02-09 10:40:45 +0800926 struct kernel64_hdr *kptr = NULL;
Abhimanyu Kapur0f79d572014-02-19 22:03:02 -0800927
Maunik Shah0f3c8ac2014-03-02 17:47:58 +0530928 if (check_format_bit())
929 boot_into_recovery = 1;
930
Deepa Dinamani41fa8d62013-05-23 13:25:36 -0700931 if (!boot_into_recovery) {
932 memset(ffbm_mode_string, '\0', sizeof(ffbm_mode_string));
933 rcode = get_ffbm(ffbm_mode_string, sizeof(ffbm_mode_string));
934 if (rcode <= 0) {
935 boot_into_ffbm = false;
936 if (rcode < 0)
937 dprintf(CRITICAL,"failed to get ffbm cookie");
938 } else
939 boot_into_ffbm = true;
940 } else
941 boot_into_ffbm = false;
Shashank Mittal23b8f422010-04-16 19:27:21 -0700942 uhdr = (struct boot_img_hdr *)EMMC_BOOT_IMG_HEADER_ADDR;
943 if (!memcmp(uhdr->magic, BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
944 dprintf(INFO, "Unified boot method!\n");
945 hdr = uhdr;
946 goto unified_boot;
947 }
Greg Griscod6250552011-06-29 14:40:23 -0700948 if (!boot_into_recovery) {
Kinson Chikf1a43512011-07-14 11:28:39 -0700949 index = partition_get_index("boot");
950 ptn = partition_get_offset(index);
951 if(ptn == 0) {
Shashank Mittal85b91f62010-10-30 10:12:38 -0700952 dprintf(CRITICAL, "ERROR: No boot partition found\n");
953 return -1;
954 }
Kinson Chikf1a43512011-07-14 11:28:39 -0700955 }
956 else {
957 index = partition_get_index("recovery");
958 ptn = partition_get_offset(index);
959 if(ptn == 0) {
Shashank Mittal85b91f62010-10-30 10:12:38 -0700960 dprintf(CRITICAL, "ERROR: No recovery partition found\n");
961 return -1;
962 }
Shashank Mittal23b8f422010-04-16 19:27:21 -0700963 }
Channagoud Kadabief0547c2015-02-10 12:57:38 -0800964 /* Set Lun for boot & recovery partitions */
965 mmc_set_lun(partition_get_lun(index));
Shashank Mittal23b8f422010-04-16 19:27:21 -0700966
Unnati Gandhi0c8e7c52014-07-17 14:33:09 +0530967 if (mmc_read(ptn + offset, (uint32_t *) buf, page_size)) {
Shashank Mittal23b8f422010-04-16 19:27:21 -0700968 dprintf(CRITICAL, "ERROR: Cannot read boot image header\n");
969 return -1;
970 }
Shashank Mittal23b8f422010-04-16 19:27:21 -0700971
972 if (memcmp(hdr->magic, BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
Kinson Chik kchik@codeaurora.org82e4ae62011-04-12 17:42:07 -0700973 dprintf(CRITICAL, "ERROR: Invalid boot image header\n");
Shashank Mittal23b8f422010-04-16 19:27:21 -0700974 return -1;
975 }
976
Subbaraman Narayanamurthyfbe13a02010-09-10 11:51:12 -0700977 if (hdr->page_size && (hdr->page_size != page_size)) {
vijay kumar2e21b3a2014-06-26 17:40:15 +0530978
979 if (hdr->page_size > BOOT_IMG_MAX_PAGE_SIZE) {
980 dprintf(CRITICAL, "ERROR: Invalid page size\n");
981 return -1;
982 }
Subbaraman Narayanamurthyfbe13a02010-09-10 11:51:12 -0700983 page_size = hdr->page_size;
984 page_mask = page_size - 1;
Shashank Mittal23b8f422010-04-16 19:27:21 -0700985 }
986
Matthew Qin49e51fa2015-02-09 10:40:45 +0800987 kernel_actual = ROUND_TO_PAGE(hdr->kernel_size, page_mask);
988 ramdisk_actual = ROUND_TO_PAGE(hdr->ramdisk_size, page_mask);
Abhimanyu Kapur0f79d572014-02-19 22:03:02 -0800989
Matthew Qin49e51fa2015-02-09 10:40:45 +0800990 image_addr = (unsigned char *)target_get_scratch_address();
991
992#if DEVICE_TREE
993 dt_actual = ROUND_TO_PAGE(hdr->dt_size, page_mask);
994 imagesize_actual = (page_size + kernel_actual + ramdisk_actual + dt_actual);
995#else
996 imagesize_actual = (page_size + kernel_actual + ramdisk_actual);
997#endif
998
999#if VERIFIED_BOOT
1000 boot_verifier_init();
1001#endif
1002
1003 if (check_aboot_addr_range_overlap((uint32_t) image_addr, imagesize_actual))
1004 {
1005 dprintf(CRITICAL, "Boot image buffer address overlaps with aboot addresses.\n");
1006 return -1;
1007 }
1008
Matthew Qinbb7923d2015-02-09 10:56:09 +08001009 /*
1010 * Update loading flow of bootimage to support compressed/uncompressed
1011 * bootimage on both 64bit and 32bit platform.
1012 * 1. Load bootimage from emmc partition onto DDR.
1013 * 2. Check if bootimage is gzip format. If yes, decompress compressed kernel
1014 * 3. Check kernel header and update kernel load addr for 64bit and 32bit
1015 * platform accordingly.
1016 * 4. Sanity Check on kernel_addr and ramdisk_addr and copy data.
1017 */
1018
Matthew Qin49e51fa2015-02-09 10:40:45 +08001019 dprintf(INFO, "Loading boot image (%d): start\n", imagesize_actual);
1020 bs_set_timestamp(BS_KERNEL_LOAD_START);
1021
Matthew Qinbb7923d2015-02-09 10:56:09 +08001022 /* Read image without signature */
Matthew Qin49e51fa2015-02-09 10:40:45 +08001023 if (mmc_read(ptn + offset, (void *)image_addr, imagesize_actual))
1024 {
1025 dprintf(CRITICAL, "ERROR: Cannot read boot image\n");
1026 return -1;
1027 }
1028
1029 dprintf(INFO, "Loading boot image (%d): done\n", imagesize_actual);
1030 bs_set_timestamp(BS_KERNEL_LOAD_DONE);
1031
1032 /* Authenticate Kernel */
1033 dprintf(INFO, "use_signed_kernel=%d, is_unlocked=%d, is_tampered=%d.\n",
1034 (int) target_use_signed_kernel(),
1035 device.is_unlocked,
1036 device.is_tampered);
1037
1038 if(target_use_signed_kernel() && (!device.is_unlocked))
1039 {
1040 offset = imagesize_actual;
1041 if (check_aboot_addr_range_overlap((uint32_t)image_addr + offset, page_size))
1042 {
1043 dprintf(CRITICAL, "Signature read buffer address overlaps with aboot addresses.\n");
1044 return -1;
1045 }
1046
1047 /* Read signature */
1048 if(mmc_read(ptn + offset, (void *)(image_addr + offset), page_size))
1049 {
1050 dprintf(CRITICAL, "ERROR: Cannot read boot image signature\n");
1051 return -1;
1052 }
1053
1054 verify_signed_bootimg((uint32_t)image_addr, imagesize_actual);
1055 } else {
1056 second_actual = ROUND_TO_PAGE(hdr->second_size, page_mask);
1057 #ifdef TZ_SAVE_KERNEL_HASH
1058 aboot_save_boot_hash_mmc((uint32_t) image_addr, imagesize_actual);
1059 #endif /* TZ_SAVE_KERNEL_HASH */
Amit Blay4aa292f2015-04-28 21:55:59 +03001060
1061#ifdef MDTP_SUPPORT
1062 {
1063 /* Verify MDTP lock.
1064 * For boot & recovery partitions, MDTP will use boot_verifier APIs,
1065 * since verification was skipped in aboot. The signature is not part of the loaded image.
1066 */
1067 mdtp_ext_partition_verification_t ext_partition;
1068 ext_partition.partition = boot_into_recovery ? MDTP_PARTITION_RECOVERY : MDTP_PARTITION_BOOT;
1069 ext_partition.integrity_state = MDTP_PARTITION_STATE_UNSET;
1070 ext_partition.page_size = page_size;
1071 ext_partition.image_addr = (uint32)image_addr;
1072 ext_partition.image_size = imagesize_actual;
1073 ext_partition.sig_avail = FALSE;
1074 mdtp_fwlock_verify_lock(&ext_partition);
1075 }
1076#endif /* MDTP_SUPPORT */
Abhimanyu Kapur0f79d572014-02-19 22:03:02 -08001077 }
1078
Channagoud Kadabia22144f2013-03-20 11:49:01 -07001079 /*
Matthew Qinbb7923d2015-02-09 10:56:09 +08001080 * Check if the kernel image is a gzip package. If yes, need to decompress it.
1081 * If not, continue booting.
1082 */
1083 if (is_gzip_package((unsigned char *)(image_addr + page_size), hdr->kernel_size))
1084 {
1085 out_addr = (unsigned char *)(image_addr + imagesize_actual + page_size);
1086 out_avai_len = target_get_max_flash_size() - imagesize_actual - page_size;
Matthew Qin0b15b322015-05-19 05:20:54 -04001087 dprintf(INFO, "decompressing kernel image: start\n");
Matthew Qinbb7923d2015-02-09 10:56:09 +08001088 rc = decompress((unsigned char *)(image_addr + page_size),
1089 hdr->kernel_size, out_addr, out_avai_len,
1090 &dtb_offset, &out_len);
1091 if (rc)
1092 {
Matthew Qin0b15b322015-05-19 05:20:54 -04001093 dprintf(CRITICAL, "decompressing kernel image failed!!!\n");
Matthew Qinbb7923d2015-02-09 10:56:09 +08001094 ASSERT(0);
1095 }
1096
Matthew Qin0b15b322015-05-19 05:20:54 -04001097 dprintf(INFO, "decompressing kernel image: done\n");
Matthew Qinbb7923d2015-02-09 10:56:09 +08001098 kptr = (struct kernel64_hdr *)out_addr;
1099 kernel_start_addr = out_addr;
1100 kernel_size = out_len;
1101 } else {
1102 kptr = (struct kernel64_hdr *)(image_addr + page_size);
1103 kernel_start_addr = (unsigned char *)(image_addr + page_size);
1104 kernel_size = hdr->kernel_size;
1105 }
1106
1107 /*
Channagoud Kadabia22144f2013-03-20 11:49:01 -07001108 * Update the kernel/ramdisk/tags address if the boot image header
1109 * has default values, these default values come from mkbootimg when
1110 * the boot image is flashed using fastboot flash:raw
1111 */
Abhimanyu Kapur0f79d572014-02-19 22:03:02 -08001112 update_ker_tags_rdisk_addr(hdr, IS_ARM64(kptr));
Channagoud Kadabia22144f2013-03-20 11:49:01 -07001113
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001114 /* Get virtual addresses since the hdr saves physical addresses. */
1115 hdr->kernel_addr = VA((addr_t)(hdr->kernel_addr));
1116 hdr->ramdisk_addr = VA((addr_t)(hdr->ramdisk_addr));
1117 hdr->tags_addr = VA((addr_t)(hdr->tags_addr));
Deepa Dinamani0e163a42013-05-24 17:08:15 -07001118
Matthew Qinbb7923d2015-02-09 10:56:09 +08001119 kernel_size = ROUND_TO_PAGE(kernel_size, page_mask);
Deepa Dinamani0e163a42013-05-24 17:08:15 -07001120 /* Check if the addresses in the header are valid. */
Matthew Qinbb7923d2015-02-09 10:56:09 +08001121 if (check_aboot_addr_range_overlap(hdr->kernel_addr, kernel_size) ||
Deepa Dinamani0e163a42013-05-24 17:08:15 -07001122 check_aboot_addr_range_overlap(hdr->ramdisk_addr, ramdisk_actual))
1123 {
1124 dprintf(CRITICAL, "kernel/ramdisk addresses overlap with aboot addresses.\n");
1125 return -1;
1126 }
1127
1128#ifndef DEVICE_TREE
1129 if (check_aboot_addr_range_overlap(hdr->tags_addr, MAX_TAGS_SIZE))
1130 {
1131 dprintf(CRITICAL, "Tags addresses overlap with aboot addresses.\n");
1132 return -1;
1133 }
1134#endif
1135
Matthew Qin49e51fa2015-02-09 10:40:45 +08001136 /* Move kernel, ramdisk and device tree to correct address */
Matthew Qinbb7923d2015-02-09 10:56:09 +08001137 memmove((void*) hdr->kernel_addr, kernel_start_addr, kernel_size);
Matthew Qin49e51fa2015-02-09 10:40:45 +08001138 memmove((void*) hdr->ramdisk_addr, (char *)(image_addr + page_size + kernel_actual), hdr->ramdisk_size);
Shashank Mittald3e54dd2014-08-28 15:24:02 -07001139
Matthew Qin49e51fa2015-02-09 10:40:45 +08001140 #if DEVICE_TREE
1141 if(hdr->dt_size) {
1142 dt_table_offset = ((uint32_t)image_addr + page_size + kernel_actual + ramdisk_actual + second_actual);
1143 table = (struct dt_table*) dt_table_offset;
Deepa Dinamani0e163a42013-05-24 17:08:15 -07001144
Matthew Qin49e51fa2015-02-09 10:40:45 +08001145 if (dev_tree_validate(table, hdr->page_size, &dt_hdr_size) != 0) {
1146 dprintf(CRITICAL, "ERROR: Cannot validate Device Tree Table \n");
1147 return -1;
1148 }
Deepa Dinamani0e163a42013-05-24 17:08:15 -07001149
Matthew Qin49e51fa2015-02-09 10:40:45 +08001150 /* Find index of device tree within device tree table */
1151 if(dev_tree_get_entry_info(table, &dt_entry) != 0){
1152 dprintf(CRITICAL, "ERROR: Getting device tree address failed\n");
1153 return -1;
1154 }
Deepa Dinamani0e163a42013-05-24 17:08:15 -07001155
Matthew Qin271927e2015-03-31 22:07:07 -04001156 if (is_gzip_package((unsigned char *)dt_table_offset + dt_entry.offset, dt_entry.size))
1157 {
1158 unsigned int compressed_size = 0;
1159 out_addr += out_len;
1160 out_avai_len -= out_len;
Matthew Qin0b15b322015-05-19 05:20:54 -04001161 dprintf(INFO, "decompressing dtb: start\n");
Matthew Qin271927e2015-03-31 22:07:07 -04001162 rc = decompress((unsigned char *)dt_table_offset + dt_entry.offset,
1163 dt_entry.size, out_addr, out_avai_len,
1164 &compressed_size, &dtb_size);
1165 if (rc)
1166 {
Matthew Qin0b15b322015-05-19 05:20:54 -04001167 dprintf(CRITICAL, "decompressing dtb failed!!!\n");
Matthew Qin271927e2015-03-31 22:07:07 -04001168 ASSERT(0);
1169 }
1170
Matthew Qin0b15b322015-05-19 05:20:54 -04001171 dprintf(INFO, "decompressing dtb: done\n");
Matthew Qin271927e2015-03-31 22:07:07 -04001172 best_match_dt_addr = out_addr;
1173 } else {
1174 best_match_dt_addr = (unsigned char *)dt_table_offset + dt_entry.offset;
1175 dtb_size = dt_entry.size;
1176 }
1177
Matthew Qin49e51fa2015-02-09 10:40:45 +08001178 /* Validate and Read device device tree in the tags_addr */
Matthew Qin271927e2015-03-31 22:07:07 -04001179 if (check_aboot_addr_range_overlap(hdr->tags_addr, dtb_size))
Deepa Dinamani0e163a42013-05-24 17:08:15 -07001180 {
1181 dprintf(CRITICAL, "Device tree addresses overlap with aboot addresses.\n");
1182 return -1;
1183 }
Shashank Mittal162244e2011-08-08 19:01:25 -07001184
Matthew Qin271927e2015-03-31 22:07:07 -04001185 memmove((void *)hdr->tags_addr, (char *)best_match_dt_addr, dtb_size);
Matthew Qin49e51fa2015-02-09 10:40:45 +08001186 } else {
1187 /* Validate the tags_addr */
1188 if (check_aboot_addr_range_overlap(hdr->tags_addr, kernel_actual))
Channagoud Kadabi82cf5c62014-08-24 22:17:34 -07001189 {
1190 dprintf(CRITICAL, "Device tree addresses overlap with aboot addresses.\n");
1191 return -1;
1192 }
Matthew Qin49e51fa2015-02-09 10:40:45 +08001193 /*
1194 * If appended dev tree is found, update the atags with
1195 * memory address to the DTB appended location on RAM.
1196 * Else update with the atags address in the kernel header
1197 */
1198 void *dtb;
Matthew Qinbb7923d2015-02-09 10:56:09 +08001199 dtb = dev_tree_appended((void*)(image_addr + page_size),
1200 hdr->kernel_size, dtb_offset,
Matthew Qin49e51fa2015-02-09 10:40:45 +08001201 (void *)hdr->tags_addr);
1202 if (!dtb) {
1203 dprintf(CRITICAL, "ERROR: Appended Device Tree Blob not found\n");
Channagoud Kadabi82cf5c62014-08-24 22:17:34 -07001204 return -1;
1205 }
Shashank Mittalcd98d472011-08-02 14:29:24 -07001206 }
Matthew Qin49e51fa2015-02-09 10:40:45 +08001207 #endif
Shashank Mittal23b8f422010-04-16 19:27:21 -07001208
Stanimir Varbanov69ec5462013-07-18 18:17:42 +03001209 if (boot_into_recovery && !device.is_unlocked && !device.is_tampered)
1210 target_load_ssd_keystore();
1211
Shashank Mittal23b8f422010-04-16 19:27:21 -07001212unified_boot:
Shashank Mittal23b8f422010-04-16 19:27:21 -07001213
Dima Zavin77e41f32013-03-06 16:10:43 -08001214 boot_linux((void *)hdr->kernel_addr, (void *)hdr->tags_addr,
Dima Zavinbd3daa02013-03-26 11:06:44 -07001215 (const char *)hdr->cmdline, board_machtype(),
Shashank Mittal23b8f422010-04-16 19:27:21 -07001216 (void *)hdr->ramdisk_addr, hdr->ramdisk_size);
1217
1218 return 0;
1219}
1220
Dima Zavin214cc642009-01-26 11:16:21 -08001221int boot_linux_from_flash(void)
1222{
1223 struct boot_img_hdr *hdr = (void*) buf;
Dima Zavin214cc642009-01-26 11:16:21 -08001224 struct ptentry *ptn;
1225 struct ptable *ptable;
1226 unsigned offset = 0;
Chandan Uddarajude85d3f2010-01-05 16:32:33 -08001227
Shashank Mittalcd98d472011-08-02 14:29:24 -07001228 unsigned char *image_addr = 0;
1229 unsigned kernel_actual;
1230 unsigned ramdisk_actual;
1231 unsigned imagesize_actual;
Amol Jadib6be5c12012-11-14 13:39:51 -08001232 unsigned second_actual;
Shashank Mittalcd98d472011-08-02 14:29:24 -07001233
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -07001234#if DEVICE_TREE
1235 struct dt_table *table;
Joel Kingaa335dc2013-06-03 16:11:08 -07001236 struct dt_entry dt_entry;
Deepa Dinamani7aaf83d2012-12-21 11:27:01 -08001237 uint32_t dt_actual;
Deepa Dinamani19648b42013-09-05 17:05:55 -07001238 uint32_t dt_hdr_size;
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -07001239#endif
1240
David Ng183a7422009-12-07 14:55:21 -08001241 if (target_is_emmc_boot()) {
1242 hdr = (struct boot_img_hdr *)EMMC_BOOT_IMG_HEADER_ADDR;
1243 if (memcmp(hdr->magic, BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
1244 dprintf(CRITICAL, "ERROR: Invalid boot image header\n");
1245 return -1;
1246 }
1247 goto continue_boot;
1248 }
1249
Dima Zavin214cc642009-01-26 11:16:21 -08001250 ptable = flash_get_ptable();
1251 if (ptable == NULL) {
1252 dprintf(CRITICAL, "ERROR: Partition table not found\n");
1253 return -1;
1254 }
1255
Chandan Uddarajude85d3f2010-01-05 16:32:33 -08001256 if(!boot_into_recovery)
1257 {
1258 ptn = ptable_find(ptable, "boot");
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -07001259
Chandan Uddarajude85d3f2010-01-05 16:32:33 -08001260 if (ptn == NULL) {
1261 dprintf(CRITICAL, "ERROR: No boot partition found\n");
1262 return -1;
1263 }
1264 }
1265 else
1266 {
1267 ptn = ptable_find(ptable, "recovery");
1268 if (ptn == NULL) {
1269 dprintf(CRITICAL, "ERROR: No recovery partition found\n");
1270 return -1;
1271 }
Dima Zavin214cc642009-01-26 11:16:21 -08001272 }
1273
Shashank Mittaldcc2e352009-11-19 19:11:16 -08001274 if (flash_read(ptn, offset, buf, page_size)) {
Dima Zavin214cc642009-01-26 11:16:21 -08001275 dprintf(CRITICAL, "ERROR: Cannot read boot image header\n");
1276 return -1;
1277 }
Dima Zavin214cc642009-01-26 11:16:21 -08001278
1279 if (memcmp(hdr->magic, BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
Kinson Chik kchik@codeaurora.org82e4ae62011-04-12 17:42:07 -07001280 dprintf(CRITICAL, "ERROR: Invalid boot image header\n");
Dima Zavin214cc642009-01-26 11:16:21 -08001281 return -1;
1282 }
1283
Shashank Mittaldcc2e352009-11-19 19:11:16 -08001284 if (hdr->page_size != page_size) {
Kinson Chik kchik@codeaurora.org82e4ae62011-04-12 17:42:07 -07001285 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 -08001286 return -1;
1287 }
1288
Channagoud Kadabia22144f2013-03-20 11:49:01 -07001289 /*
1290 * Update the kernel/ramdisk/tags address if the boot image header
1291 * has default values, these default values come from mkbootimg when
1292 * the boot image is flashed using fastboot flash:raw
1293 */
Abhimanyu Kapur0f79d572014-02-19 22:03:02 -08001294 update_ker_tags_rdisk_addr(hdr, false);
Channagoud Kadabia22144f2013-03-20 11:49:01 -07001295
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001296 /* Get virtual addresses since the hdr saves physical addresses. */
Deepa Dinamani0e163a42013-05-24 17:08:15 -07001297 hdr->kernel_addr = VA((addr_t)(hdr->kernel_addr));
1298 hdr->ramdisk_addr = VA((addr_t)(hdr->ramdisk_addr));
1299 hdr->tags_addr = VA((addr_t)(hdr->tags_addr));
1300
1301 kernel_actual = ROUND_TO_PAGE(hdr->kernel_size, page_mask);
1302 ramdisk_actual = ROUND_TO_PAGE(hdr->ramdisk_size, page_mask);
1303
1304 /* Check if the addresses in the header are valid. */
1305 if (check_aboot_addr_range_overlap(hdr->kernel_addr, kernel_actual) ||
1306 check_aboot_addr_range_overlap(hdr->ramdisk_addr, ramdisk_actual))
1307 {
1308 dprintf(CRITICAL, "kernel/ramdisk addresses overlap with aboot addresses.\n");
1309 return -1;
1310 }
1311
1312#ifndef DEVICE_TREE
1313 if (check_aboot_addr_range_overlap(hdr->tags_addr, MAX_TAGS_SIZE))
1314 {
1315 dprintf(CRITICAL, "Tags addresses overlap with aboot addresses.\n");
1316 return -1;
1317 }
1318#endif
Deepa Dinamani0bf2f442012-10-19 11:41:06 -07001319
Shashank Mittalcd98d472011-08-02 14:29:24 -07001320 /* Authenticate Kernel */
Deepa Dinamani23b60d42013-06-24 18:10:52 -07001321 if(target_use_signed_kernel() && (!device.is_unlocked))
Shashank Mittalcd98d472011-08-02 14:29:24 -07001322 {
1323 image_addr = (unsigned char *)target_get_scratch_address();
Deepa Dinamani0e163a42013-05-24 17:08:15 -07001324 offset = 0;
1325
Deepa Dinamani7aaf83d2012-12-21 11:27:01 -08001326#if DEVICE_TREE
1327 dt_actual = ROUND_TO_PAGE(hdr->dt_size, page_mask);
1328 imagesize_actual = (page_size + kernel_actual + ramdisk_actual + dt_actual);
Deepa Dinamani0e163a42013-05-24 17:08:15 -07001329
1330 if (check_aboot_addr_range_overlap(hdr->tags_addr, hdr->dt_size))
1331 {
1332 dprintf(CRITICAL, "Device tree addresses overlap with aboot addresses.\n");
1333 return -1;
1334 }
Deepa Dinamani7aaf83d2012-12-21 11:27:01 -08001335#else
Shashank Mittalcd98d472011-08-02 14:29:24 -07001336 imagesize_actual = (page_size + kernel_actual + ramdisk_actual);
Deepa Dinamani7aaf83d2012-12-21 11:27:01 -08001337#endif
Shashank Mittal162244e2011-08-08 19:01:25 -07001338
Amol Jadib6be5c12012-11-14 13:39:51 -08001339 dprintf(INFO, "Loading boot image (%d): start\n", imagesize_actual);
Amol Jadi492d5a52013-03-15 16:12:34 -07001340 bs_set_timestamp(BS_KERNEL_LOAD_START);
Amol Jadib6be5c12012-11-14 13:39:51 -08001341
Shashank Mittalcd98d472011-08-02 14:29:24 -07001342 /* Read image without signature */
1343 if (flash_read(ptn, offset, (void *)image_addr, imagesize_actual))
1344 {
1345 dprintf(CRITICAL, "ERROR: Cannot read boot image\n");
1346 return -1;
1347 }
Dima Zavin214cc642009-01-26 11:16:21 -08001348
Amol Jadib6be5c12012-11-14 13:39:51 -08001349 dprintf(INFO, "Loading boot image (%d): done\n", imagesize_actual);
Amol Jadi492d5a52013-03-15 16:12:34 -07001350 bs_set_timestamp(BS_KERNEL_LOAD_DONE);
Amol Jadib6be5c12012-11-14 13:39:51 -08001351
Shashank Mittalcd98d472011-08-02 14:29:24 -07001352 offset = imagesize_actual;
1353 /* Read signature */
1354 if (flash_read(ptn, offset, (void *)(image_addr + offset), page_size))
1355 {
1356 dprintf(CRITICAL, "ERROR: Cannot read boot image signature\n");
Deepa Dinamani0e163a42013-05-24 17:08:15 -07001357 return -1;
Shashank Mittalcd98d472011-08-02 14:29:24 -07001358 }
Shashank Mittalcd98d472011-08-02 14:29:24 -07001359
Unnati Gandhi0c8e7c52014-07-17 14:33:09 +05301360 verify_signed_bootimg((uint32_t)image_addr, imagesize_actual);
Shashank Mittalcd98d472011-08-02 14:29:24 -07001361
1362 /* Move kernel and ramdisk to correct address */
Matthew Qinbb7923d2015-02-09 10:56:09 +08001363 memmove((void*) hdr->kernel_addr, (char*) (image_addr + page_size), hdr->kernel_size);
1364 memmove((void*) hdr->ramdisk_addr, (char*) (image_addr + page_size + kernel_actual), hdr->ramdisk_size);
Deepa Dinamani7aaf83d2012-12-21 11:27:01 -08001365#if DEVICE_TREE
Deepa Dinamani0e163a42013-05-24 17:08:15 -07001366 /* Validate and Read device device tree in the "tags_add */
Joel Kingaa335dc2013-06-03 16:11:08 -07001367 if (check_aboot_addr_range_overlap(hdr->tags_addr, dt_entry.size))
Deepa Dinamani0e163a42013-05-24 17:08:15 -07001368 {
1369 dprintf(CRITICAL, "Device tree addresses overlap with aboot addresses.\n");
1370 return -1;
1371 }
1372
Deepa Dinamani7aaf83d2012-12-21 11:27:01 -08001373 memmove((void*) hdr->tags_addr, (char *)(image_addr + page_size + kernel_actual + ramdisk_actual), hdr->dt_size);
1374#endif
Shashank Mittal162244e2011-08-08 19:01:25 -07001375
1376 /* Make sure everything from scratch address is read before next step!*/
Shashank Mittala0032282011-08-26 14:50:11 -07001377 if(device.is_tampered)
Shashank Mittal162244e2011-08-08 19:01:25 -07001378 {
1379 write_device_info_flash(&device);
1380 }
Channagoud Kadabi5c86fe32012-02-16 10:58:48 +05301381#if USE_PCOM_SECBOOT
1382 set_tamper_flag(device.is_tampered);
1383#endif
Shashank Mittalcd98d472011-08-02 14:29:24 -07001384 }
1385 else
1386 {
Shashank Mittal162244e2011-08-08 19:01:25 -07001387 offset = page_size;
1388
Amol Jadib6be5c12012-11-14 13:39:51 -08001389 kernel_actual = ROUND_TO_PAGE(hdr->kernel_size, page_mask);
1390 ramdisk_actual = ROUND_TO_PAGE(hdr->ramdisk_size, page_mask);
1391 second_actual = ROUND_TO_PAGE(hdr->second_size, page_mask);
1392
1393 dprintf(INFO, "Loading boot image (%d): start\n",
1394 kernel_actual + ramdisk_actual);
Amol Jadi492d5a52013-03-15 16:12:34 -07001395 bs_set_timestamp(BS_KERNEL_LOAD_START);
Amol Jadib6be5c12012-11-14 13:39:51 -08001396
1397 if (flash_read(ptn, offset, (void *)hdr->kernel_addr, kernel_actual)) {
Shashank Mittalcd98d472011-08-02 14:29:24 -07001398 dprintf(CRITICAL, "ERROR: Cannot read kernel image\n");
1399 return -1;
1400 }
Amol Jadib6be5c12012-11-14 13:39:51 -08001401 offset += kernel_actual;
Shashank Mittalcd98d472011-08-02 14:29:24 -07001402
Amol Jadib6be5c12012-11-14 13:39:51 -08001403 if (flash_read(ptn, offset, (void *)hdr->ramdisk_addr, ramdisk_actual)) {
Shashank Mittalcd98d472011-08-02 14:29:24 -07001404 dprintf(CRITICAL, "ERROR: Cannot read ramdisk image\n");
1405 return -1;
1406 }
Amol Jadib6be5c12012-11-14 13:39:51 -08001407 offset += ramdisk_actual;
1408
1409 dprintf(INFO, "Loading boot image (%d): done\n",
1410 kernel_actual + ramdisk_actual);
Amol Jadi492d5a52013-03-15 16:12:34 -07001411 bs_set_timestamp(BS_KERNEL_LOAD_DONE);
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -07001412
1413 if(hdr->second_size != 0) {
Amol Jadib6be5c12012-11-14 13:39:51 -08001414 offset += second_actual;
1415 /* Second image loading not implemented. */
1416 ASSERT(0);
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -07001417 }
1418
1419#if DEVICE_TREE
1420 if(hdr->dt_size != 0) {
1421
1422 /* Read the device tree table into buffer */
1423 if(flash_read(ptn, offset, (void *) dt_buf, page_size)) {
1424 dprintf(CRITICAL, "ERROR: Cannot read the Device Tree Table\n");
1425 return -1;
1426 }
1427
1428 table = (struct dt_table*) dt_buf;
1429
Deepa Dinamani19648b42013-09-05 17:05:55 -07001430 if (dev_tree_validate(table, hdr->page_size, &dt_hdr_size) != 0) {
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -07001431 dprintf(CRITICAL, "ERROR: Cannot validate Device Tree Table \n");
1432 return -1;
1433 }
1434
Deepa Dinamani19648b42013-09-05 17:05:55 -07001435 table = (struct dt_table*) memalign(CACHE_LINE, dt_hdr_size);
1436 if (!table)
1437 return -1;
1438
1439 /* Read the entire device tree table into buffer */
1440 if(flash_read(ptn, offset, (void *)table, dt_hdr_size)) {
1441 dprintf(CRITICAL, "ERROR: Cannot read the Device Tree Table\n");
1442 return -1;
1443 }
1444
1445
Joel Kingaa335dc2013-06-03 16:11:08 -07001446 /* Find index of device tree within device tree table */
1447 if(dev_tree_get_entry_info(table, &dt_entry) != 0){
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -07001448 dprintf(CRITICAL, "ERROR: Getting device tree address failed\n");
1449 return -1;
1450 }
1451
Deepa Dinamani0e163a42013-05-24 17:08:15 -07001452 /* Validate and Read device device tree in the "tags_add */
Joel Kingaa335dc2013-06-03 16:11:08 -07001453 if (check_aboot_addr_range_overlap(hdr->tags_addr, dt_entry.size))
Deepa Dinamani0e163a42013-05-24 17:08:15 -07001454 {
1455 dprintf(CRITICAL, "Device tree addresses overlap with aboot addresses.\n");
1456 return -1;
1457 }
1458
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -07001459 /* Read device device tree in the "tags_add */
Joel Kingaa335dc2013-06-03 16:11:08 -07001460 if(flash_read(ptn, offset + dt_entry.offset,
1461 (void *)hdr->tags_addr, dt_entry.size)) {
Deepa Dinamani28c0ffe2012-09-24 11:45:21 -07001462 dprintf(CRITICAL, "ERROR: Cannot read device tree\n");
1463 return -1;
1464 }
1465 }
1466#endif
1467
Shashank Mittalcd98d472011-08-02 14:29:24 -07001468 }
David Ng183a7422009-12-07 14:55:21 -08001469continue_boot:
Dima Zavin214cc642009-01-26 11:16:21 -08001470
Dima Zavin214cc642009-01-26 11:16:21 -08001471 /* TODO: create/pass atags to kernel */
1472
Ajay Dudanie28a6072011-07-01 13:59:46 -07001473 boot_linux((void *)hdr->kernel_addr, (void *)hdr->tags_addr,
Dima Zavinbd3daa02013-03-26 11:06:44 -07001474 (const char *)hdr->cmdline, board_machtype(),
Dima Zavin214cc642009-01-26 11:16:21 -08001475 (void *)hdr->ramdisk_addr, hdr->ramdisk_size);
1476
1477 return 0;
1478}
Brian Swetland9c4c0752009-01-25 16:23:50 -08001479
Shashank Mittal162244e2011-08-08 19:01:25 -07001480void write_device_info_mmc(device_info *dev)
1481{
Shashank Mittal162244e2011-08-08 19:01:25 -07001482 unsigned long long ptn = 0;
1483 unsigned long long size;
1484 int index = INVALID_PTN;
Channagoud Kadabi749b0f82013-09-10 22:36:02 -07001485 uint32_t blocksize;
Sundarajan Srinivasand3514bb2013-12-04 17:02:00 -08001486 uint8_t lun = 0;
Channagoud Kadabi80a182b2015-03-11 17:04:23 -07001487 uint32_t ret = 0;
Shashank Mittal162244e2011-08-08 19:01:25 -07001488
Channagoud Kadabi80a182b2015-03-11 17:04:23 -07001489 if (devinfo_present)
1490 index = partition_get_index("devinfo");
1491 else
1492 index = partition_get_index("aboot");
Channagoud Kadabi5d0371c2014-10-21 22:27:07 -07001493
Shashank Mittal162244e2011-08-08 19:01:25 -07001494 ptn = partition_get_offset(index);
1495 if(ptn == 0)
1496 {
1497 return;
1498 }
1499
Sundarajan Srinivasand3514bb2013-12-04 17:02:00 -08001500 lun = partition_get_lun(index);
1501 mmc_set_lun(lun);
1502
Shashank Mittal162244e2011-08-08 19:01:25 -07001503 size = partition_get_size(index);
1504
Channagoud Kadabi749b0f82013-09-10 22:36:02 -07001505 blocksize = mmc_get_device_blocksize();
1506
Channagoud Kadabi80a182b2015-03-11 17:04:23 -07001507 if (devinfo_present)
1508 ret = mmc_write(ptn, blocksize, (void *)info_buf);
1509 else
1510 ret = mmc_write((ptn + size - blocksize), blocksize, (void *)info_buf);
1511 if (ret)
Shashank Mittal162244e2011-08-08 19:01:25 -07001512 {
1513 dprintf(CRITICAL, "ERROR: Cannot write device info\n");
1514 return;
1515 }
1516}
1517
Channagoud Kadabi036c6052015-02-09 15:19:59 -08001518void read_device_info_mmc(struct device_info *info)
Shashank Mittal162244e2011-08-08 19:01:25 -07001519{
Shashank Mittal162244e2011-08-08 19:01:25 -07001520 unsigned long long ptn = 0;
1521 unsigned long long size;
1522 int index = INVALID_PTN;
Channagoud Kadabi749b0f82013-09-10 22:36:02 -07001523 uint32_t blocksize;
Channagoud Kadabi80a182b2015-03-11 17:04:23 -07001524 uint32_t ret = 0;
Shashank Mittal162244e2011-08-08 19:01:25 -07001525
Channagoud Kadabi80a182b2015-03-11 17:04:23 -07001526 if ((index = partition_get_index("devinfo")) < 0)
1527 {
1528 devinfo_present = false;
1529 index = partition_get_index("aboot");
1530 }
Channagoud Kadabi5d0371c2014-10-21 22:27:07 -07001531
Shashank Mittal162244e2011-08-08 19:01:25 -07001532 ptn = partition_get_offset(index);
1533 if(ptn == 0)
1534 {
1535 return;
1536 }
1537
Channagoud Kadabi5d0371c2014-10-21 22:27:07 -07001538 mmc_set_lun(partition_get_lun(index));
1539
Shashank Mittal162244e2011-08-08 19:01:25 -07001540 size = partition_get_size(index);
1541
Channagoud Kadabi749b0f82013-09-10 22:36:02 -07001542 blocksize = mmc_get_device_blocksize();
1543
Channagoud Kadabi80a182b2015-03-11 17:04:23 -07001544 if (devinfo_present)
1545 ret = mmc_read(ptn, (void *)info_buf, blocksize);
1546 else
1547 ret = mmc_read((ptn + size - blocksize), (void *)info_buf, blocksize);
1548 if (ret)
Shashank Mittal162244e2011-08-08 19:01:25 -07001549 {
1550 dprintf(CRITICAL, "ERROR: Cannot read device info\n");
1551 return;
1552 }
1553
Shashank Mittal162244e2011-08-08 19:01:25 -07001554}
1555
1556void write_device_info_flash(device_info *dev)
1557{
Sridhar Parasuram7e16d172015-07-05 11:35:23 -07001558 struct device_info *info = memalign(PAGE_SIZE, ROUNDUP(BOOT_IMG_MAX_PAGE_SIZE, PAGE_SIZE));
Shashank Mittal162244e2011-08-08 19:01:25 -07001559 struct ptentry *ptn;
1560 struct ptable *ptable;
Sridhar Parasuram7e16d172015-07-05 11:35:23 -07001561 if(info == NULL)
1562 {
1563 dprintf(CRITICAL, "Failed to allocate memory for device info struct\n");
1564 ASSERT(0);
1565 }
1566 info_buf = info;
Shashank Mittal162244e2011-08-08 19:01:25 -07001567 ptable = flash_get_ptable();
1568 if (ptable == NULL)
1569 {
1570 dprintf(CRITICAL, "ERROR: Partition table not found\n");
1571 return;
1572 }
1573
1574 ptn = ptable_find(ptable, "devinfo");
1575 if (ptn == NULL)
1576 {
Smita Ghosh670c8b82015-05-07 09:30:03 -07001577 dprintf(CRITICAL, "ERROR: No devinfo partition found\n");
Shashank Mittal162244e2011-08-08 19:01:25 -07001578 return;
1579 }
1580
1581 memcpy(info, dev, sizeof(device_info));
1582
1583 if (flash_write(ptn, 0, (void *)info_buf, page_size))
1584 {
1585 dprintf(CRITICAL, "ERROR: Cannot write device info\n");
1586 return;
1587 }
Sridhar Parasuram7e16d172015-07-05 11:35:23 -07001588 free(info);
Shashank Mittal162244e2011-08-08 19:01:25 -07001589}
1590
vijay kumarc65876c2015-04-24 13:29:16 +05301591static int read_allow_oem_unlock(device_info *dev)
1592{
1593 const char *ptn_name = "frp";
1594 unsigned offset;
1595 int index;
1596 unsigned long long ptn;
1597 unsigned long long ptn_size;
1598 unsigned blocksize = mmc_get_device_blocksize();
1599 char buf[blocksize];
1600
1601 index = partition_get_index(ptn_name);
1602 if (index == INVALID_PTN)
1603 {
1604 dprintf(CRITICAL, "No '%s' partition found\n", ptn_name);
1605 return -1;
1606 }
1607
1608 ptn = partition_get_offset(index);
1609 ptn_size = partition_get_size(index);
1610 offset = ptn_size - blocksize;
1611
1612 if (mmc_read(ptn + offset, (void *)buf, sizeof(buf)))
1613 {
1614 dprintf(CRITICAL, "Reading MMC failed\n");
1615 return -1;
1616 }
1617
1618 /*is_allow_unlock is a bool value stored at the LSB of last byte*/
1619 is_allow_unlock = buf[blocksize-1] & 0x01;
1620 return 0;
1621}
1622
1623static int write_allow_oem_unlock(bool allow_unlock)
1624{
1625 const char *ptn_name = "frp";
1626 unsigned offset;
1627
1628 int index;
1629 unsigned long long ptn;
1630 unsigned long long ptn_size;
1631 unsigned blocksize = mmc_get_device_blocksize();
1632 char buf[blocksize];
1633
1634 index = partition_get_index(ptn_name);
1635 if (index == INVALID_PTN)
1636 {
1637 dprintf(CRITICAL, "No '%s' partition found\n", ptn_name);
1638 return -1;
1639 }
1640
1641 ptn = partition_get_offset(index);
1642 ptn_size = partition_get_size(index);
1643 offset = ptn_size - blocksize;
1644
1645 if (mmc_read(ptn + offset, (void *)buf, sizeof(buf)))
1646 {
1647 dprintf(CRITICAL, "Reading MMC failed\n");
1648 return -1;
1649 }
1650
1651 /*is_allow_unlock is a bool value stored at the LSB of last byte*/
1652 buf[blocksize-1] = allow_unlock;
1653 if (mmc_write(ptn + offset, blocksize, buf))
1654 {
1655 dprintf(CRITICAL, "Writing MMC failed\n");
1656 return -1;
1657 }
1658
1659 return 0;
1660}
1661
Shashank Mittal162244e2011-08-08 19:01:25 -07001662void read_device_info_flash(device_info *dev)
1663{
Sridhar Parasuram7e16d172015-07-05 11:35:23 -07001664 struct device_info *info = memalign(PAGE_SIZE, ROUNDUP(BOOT_IMG_MAX_PAGE_SIZE, PAGE_SIZE));
Shashank Mittal162244e2011-08-08 19:01:25 -07001665 struct ptentry *ptn;
1666 struct ptable *ptable;
Sridhar Parasuram7e16d172015-07-05 11:35:23 -07001667 if(info == NULL)
1668 {
1669 dprintf(CRITICAL, "Failed to allocate memory for device info struct\n");
1670 ASSERT(0);
1671 }
1672 info_buf = info;
Shashank Mittal162244e2011-08-08 19:01:25 -07001673 ptable = flash_get_ptable();
1674 if (ptable == NULL)
1675 {
1676 dprintf(CRITICAL, "ERROR: Partition table not found\n");
1677 return;
1678 }
1679
1680 ptn = ptable_find(ptable, "devinfo");
1681 if (ptn == NULL)
1682 {
Smita Ghosh670c8b82015-05-07 09:30:03 -07001683 dprintf(CRITICAL, "ERROR: No devinfo partition found\n");
Shashank Mittal162244e2011-08-08 19:01:25 -07001684 return;
1685 }
1686
1687 if (flash_read(ptn, 0, (void *)info_buf, page_size))
1688 {
1689 dprintf(CRITICAL, "ERROR: Cannot write device info\n");
1690 return;
1691 }
1692
1693 if (memcmp(info->magic, DEVICE_MAGIC, DEVICE_MAGIC_SIZE))
1694 {
Shashank Mittal162244e2011-08-08 19:01:25 -07001695 memcpy(info->magic, DEVICE_MAGIC, DEVICE_MAGIC_SIZE);
1696 info->is_unlocked = 0;
Shashank Mittala0032282011-08-26 14:50:11 -07001697 info->is_tampered = 0;
Shashank Mittal162244e2011-08-08 19:01:25 -07001698 write_device_info_flash(info);
1699 }
1700 memcpy(dev, info, sizeof(device_info));
Sridhar Parasuram7e16d172015-07-05 11:35:23 -07001701 free(info);
Shashank Mittal162244e2011-08-08 19:01:25 -07001702}
1703
1704void write_device_info(device_info *dev)
1705{
1706 if(target_is_emmc_boot())
1707 {
Sridhar Parasuram7e16d172015-07-05 11:35:23 -07001708 struct device_info *info = memalign(PAGE_SIZE, ROUNDUP(BOOT_IMG_MAX_PAGE_SIZE, PAGE_SIZE));
1709 if(info == NULL)
1710 {
1711 dprintf(CRITICAL, "Failed to allocate memory for device info struct\n");
1712 ASSERT(0);
1713 }
1714 info_buf = info;
Channagoud Kadabi036c6052015-02-09 15:19:59 -08001715 memcpy(info, dev, sizeof(struct device_info));
1716
1717#if USE_RPMB_FOR_DEVINFO
1718 if (is_secure_boot_enable())
Sridhar Parasuram7e16d172015-07-05 11:35:23 -07001719 write_device_info_rpmb((void*) info, PAGE_SIZE);
Channagoud Kadabic80cb492015-04-28 16:08:28 -07001720 else
1721 write_device_info_mmc(info);
Channagoud Kadabi036c6052015-02-09 15:19:59 -08001722#else
1723 write_device_info_mmc(info);
1724#endif
Sridhar Parasuram7e16d172015-07-05 11:35:23 -07001725 free(info);
Shashank Mittal162244e2011-08-08 19:01:25 -07001726 }
1727 else
1728 {
1729 write_device_info_flash(dev);
1730 }
1731}
1732
1733void read_device_info(device_info *dev)
1734{
1735 if(target_is_emmc_boot())
1736 {
Sridhar Parasuram7e16d172015-07-05 11:35:23 -07001737 struct device_info *info = memalign(PAGE_SIZE, ROUNDUP(BOOT_IMG_MAX_PAGE_SIZE, PAGE_SIZE));
1738 if(info == NULL)
1739 {
1740 dprintf(CRITICAL, "Failed to allocate memory for device info struct\n");
1741 ASSERT(0);
1742 }
1743 info_buf = info;
Channagoud Kadabi036c6052015-02-09 15:19:59 -08001744
1745#if USE_RPMB_FOR_DEVINFO
1746 if (is_secure_boot_enable())
Sridhar Parasuram7e16d172015-07-05 11:35:23 -07001747 read_device_info_rpmb((void*) info, PAGE_SIZE);
Channagoud Kadabic80cb492015-04-28 16:08:28 -07001748 else
1749 read_device_info_mmc(info);
Channagoud Kadabi036c6052015-02-09 15:19:59 -08001750#else
1751 read_device_info_mmc(info);
1752#endif
1753
1754 if (memcmp(info->magic, DEVICE_MAGIC, DEVICE_MAGIC_SIZE))
1755 {
1756 memcpy(info->magic, DEVICE_MAGIC, DEVICE_MAGIC_SIZE);
Channagoud Kadabi05f78ba2015-07-06 11:58:14 -07001757 if (is_secure_boot_enable())
1758 info->is_unlocked = 0;
1759 else
Channagoud Kadabi2fda4092015-07-07 13:34:11 -07001760 info->is_unlocked = 1;
Channagoud Kadabi036c6052015-02-09 15:19:59 -08001761 info->is_tampered = 0;
1762 info->charger_screen_enabled = 0;
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");
Channagoud Kadabi90869ce2015-04-27 11:15:14 -07003187#if ENABLE_WBC
3188 if (!pm_appsbl_display_init_done())
3189 target_display_init(device.display_panel);
3190 else
3191 display_image_on_screen();
3192#else
lijuang99c02d82015-02-13 19:04:34 +08003193 target_display_init(device.display_panel);
Channagoud Kadabi90869ce2015-04-27 11:15:14 -07003194#endif
lijuang99c02d82015-02-13 19:04:34 +08003195 dprintf(SPEW, "Display Init: Done\n");
3196#if NO_ALARM_DISPLAY
3197 }
3198#endif
3199#endif
Aravind Venkateswaran8f076242014-02-25 16:25:30 -08003200
Greg Griscod6250552011-06-29 14:40:23 -07003201 target_serialno((unsigned char *) sn_buf);
Ajay Dudanib06c05f2011-05-12 14:46:10 -07003202 dprintf(SPEW,"serial number: %s\n",sn_buf);
Subbaraman Narayanamurthyf17b4ae2011-02-16 20:19:56 -08003203
Dhaval Patel223ec952013-07-18 14:49:44 -07003204 memset(display_panel_buf, '\0', MAX_PANEL_BUF_SIZE);
3205
Matthew Qindefd5562014-07-11 18:02:40 +08003206 /*
3207 * Check power off reason if user force reset,
3208 * if yes phone will do normal boot.
3209 */
3210 if (is_user_force_reset())
3211 goto normal_boot;
3212
Chandan Uddaraju2943fd62010-06-21 10:56:39 -07003213 /* Check if we should do something other than booting up */
Ameya Thakur0b9c2442013-05-10 13:22:56 -07003214 if (keys_get_state(KEY_VOLUMEUP) && keys_get_state(KEY_VOLUMEDOWN))
Subbaraman Narayanamurthy0e445b02011-06-19 21:34:46 -07003215 {
Pavel Nedeva4c9d3a2013-05-15 14:42:34 +03003216 dprintf(ALWAYS,"dload mode key sequence detected\n");
3217 if (set_download_mode(EMERGENCY_DLOAD))
Ameya Thakur0b9c2442013-05-10 13:22:56 -07003218 {
Pavel Nedeva4c9d3a2013-05-15 14:42:34 +03003219 dprintf(CRITICAL,"dload mode not supported by target\n");
Ameya Thakur0b9c2442013-05-10 13:22:56 -07003220 }
3221 else
3222 {
Aparna Mallavarapu0751f7f2014-04-01 22:40:39 +05303223 reboot_device(DLOAD);
Pavel Nedeva4c9d3a2013-05-15 14:42:34 +03003224 dprintf(CRITICAL,"Failed to reboot into dload mode\n");
Ameya Thakur0b9c2442013-05-10 13:22:56 -07003225 }
3226 boot_into_fastboot = true;
3227 }
3228 if (!boot_into_fastboot)
3229 {
3230 if (keys_get_state(KEY_HOME) || keys_get_state(KEY_VOLUMEUP))
3231 boot_into_recovery = 1;
3232 if (!boot_into_recovery &&
3233 (keys_get_state(KEY_BACK) || keys_get_state(KEY_VOLUMEDOWN)))
Pavel Nedev5d91d412013-04-29 11:34:24 +03003234 boot_into_fastboot = true;
Subbaraman Narayanamurthy0e445b02011-06-19 21:34:46 -07003235 }
Shashank Mittald8c42bf2010-06-09 15:44:28 -07003236 #if NO_KEYPAD_DRIVER
Kinson Chik0b1c8162011-08-31 16:31:57 -07003237 if (fastboot_trigger())
Pavel Nedev5d91d412013-04-29 11:34:24 +03003238 boot_into_fastboot = true;
Shashank Mittald8c42bf2010-06-09 15:44:28 -07003239 #endif
Chandan Uddarajubedca152010-06-02 23:05:15 -07003240
Ajay Dudani77421292010-10-27 19:34:06 -07003241 reboot_mode = check_reboot_mode();
lijuang72875802015-02-10 10:35:12 +08003242 hard_reboot_mode = check_hard_reboot_mode();
3243 if (reboot_mode == RECOVERY_MODE ||
3244 hard_reboot_mode == RECOVERY_HARD_RESET_MODE) {
Ajay Dudani77421292010-10-27 19:34:06 -07003245 boot_into_recovery = 1;
lijuang72875802015-02-10 10:35:12 +08003246 } else if(reboot_mode == FASTBOOT_MODE ||
3247 hard_reboot_mode == FASTBOOT_HARD_RESET_MODE) {
Pavel Nedev5d91d412013-04-29 11:34:24 +03003248 boot_into_fastboot = true;
lijuang72875802015-02-10 10:35:12 +08003249 } else if(reboot_mode == ALARM_BOOT ||
3250 hard_reboot_mode == RTC_HARD_RESET_MODE) {
Matthew Qind886f3c2014-01-17 16:52:01 +08003251 boot_reason_alarm = true;
Ajay Dudani77421292010-10-27 19:34:06 -07003252 }
3253
Matthew Qindefd5562014-07-11 18:02:40 +08003254normal_boot:
Pavel Nedev5d91d412013-04-29 11:34:24 +03003255 if (!boot_into_fastboot)
Shashank Mittald8c42bf2010-06-09 15:44:28 -07003256 {
Pavel Nedev5d91d412013-04-29 11:34:24 +03003257 if (target_is_emmc_boot())
Shashank Mittala0032282011-08-26 14:50:11 -07003258 {
Pavel Nedev5d91d412013-04-29 11:34:24 +03003259 if(emmc_recovery_init())
3260 dprintf(ALWAYS,"error in emmc_recovery_init\n");
3261 if(target_use_signed_kernel())
Shashank Mittala0032282011-08-26 14:50:11 -07003262 {
Pavel Nedev5d91d412013-04-29 11:34:24 +03003263 if((device.is_unlocked) || (device.is_tampered))
3264 {
3265 #ifdef TZ_TAMPER_FUSE
3266 set_tamper_fuse_cmd();
3267 #endif
3268 #if USE_PCOM_SECBOOT
3269 set_tamper_flag(device.is_tampered);
3270 #endif
3271 }
Shashank Mittala0032282011-08-26 14:50:11 -07003272 }
Amit Blay6281ebc2015-01-11 14:44:08 +02003273
Pavel Nedev5d91d412013-04-29 11:34:24 +03003274 boot_linux_from_mmc();
Shashank Mittala0032282011-08-26 14:50:11 -07003275 }
Pavel Nedev5d91d412013-04-29 11:34:24 +03003276 else
3277 {
3278 recovery_init();
3279 #if USE_PCOM_SECBOOT
3280 if((device.is_unlocked) || (device.is_tampered))
3281 set_tamper_flag(device.is_tampered);
3282 #endif
3283 boot_linux_from_flash();
3284 }
3285 dprintf(CRITICAL, "ERROR: Could not do normal boot. Reverting "
3286 "to fastboot mode.\n");
Shashank Mittald8c42bf2010-06-09 15:44:28 -07003287 }
Chandan Uddaraju2943fd62010-06-21 10:56:39 -07003288
Amol Jadi5edf3552013-07-23 14:15:34 -07003289 /* We are here means regular boot did not happen. Start fastboot. */
Channagoud Kadabi4c4884e2013-04-09 17:12:13 -07003290
Amol Jadi5edf3552013-07-23 14:15:34 -07003291 /* register aboot specific fastboot commands */
3292 aboot_fastboot_register_commands();
Amol Jadi57abe4c2011-05-24 15:47:27 -07003293
Amol Jadi5edf3552013-07-23 14:15:34 -07003294 /* dump partition table for debug info */
Kinson Chikf1a43512011-07-14 11:28:39 -07003295 partition_dump();
Amol Jadi5edf3552013-07-23 14:15:34 -07003296
3297 /* initialize and start fastboot */
3298 fastboot_init(target_get_scratch_address(), target_get_max_flash_size());
Brian Swetland9c4c0752009-01-25 16:23:50 -08003299}
3300
Deepa Dinamani41fa8d62013-05-23 13:25:36 -07003301uint32_t get_page_size()
3302{
3303 return page_size;
3304}
3305
Amir Samuelov57a6fa22013-06-05 16:36:43 +03003306/*
3307 * Calculated and save hash (SHA256) for non-signed boot image.
3308 *
Channagoud Kadabi82cf5c62014-08-24 22:17:34 -07003309 * @param image_addr - Boot image address
3310 * @param image_size - Size of the boot image
Amir Samuelov57a6fa22013-06-05 16:36:43 +03003311 *
3312 * @return int - 0 on success, negative value on failure.
3313 */
Channagoud Kadabi82cf5c62014-08-24 22:17:34 -07003314static int aboot_save_boot_hash_mmc(uint32_t image_addr, uint32_t image_size)
Amir Samuelov57a6fa22013-06-05 16:36:43 +03003315{
Channagoud Kadabi82cf5c62014-08-24 22:17:34 -07003316 unsigned int digest[8];
3317#if IMAGE_VERIF_ALGO_SHA1
3318 uint32_t auth_algo = CRYPTO_AUTH_ALG_SHA1;
3319#else
3320 uint32_t auth_algo = CRYPTO_AUTH_ALG_SHA256;
3321#endif
Amir Samuelov57a6fa22013-06-05 16:36:43 +03003322
Channagoud Kadabi82cf5c62014-08-24 22:17:34 -07003323 target_crypto_init_params();
Veera Sundaram Sankaranf9915462014-12-09 11:54:59 -08003324 hash_find((unsigned char *) image_addr, image_size, (unsigned char *)&digest, auth_algo);
Amir Samuelov57a6fa22013-06-05 16:36:43 +03003325
3326 save_kernel_hash_cmd(digest);
Channagoud Kadabi82cf5c62014-08-24 22:17:34 -07003327 dprintf(INFO, "aboot_save_boot_hash_mmc: imagesize_actual size %d bytes.\n", (int) image_size);
Amir Samuelov57a6fa22013-06-05 16:36:43 +03003328
3329 return 0;
3330}
3331
Brian Swetland9c4c0752009-01-25 16:23:50 -08003332APP_START(aboot)
3333 .init = aboot_init,
3334APP_END