[v2,1/4] add code to handle Android sparse image format

Message ID 1409248434-25762-2-git-send-email-srae@broadcom.com
State Superseded
Headers show

Commit Message

Steve Rae Aug. 28, 2014, 5:53 p.m.
Add original file (pristine) from :
  https://www.codeaurora.org/cgit/quic/la/kernel/lk/plain/app/aboot/aboot.c?h=master
[3b5092d20bd15a7a2879c13e9f64acc48d04af2d]

Signed-off-by: Steve Rae <srae@broadcom.com>
---

Changes in v2: None

 common/aboot.c | 2643 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 2643 insertions(+)
 create mode 100644 common/aboot.c

Comments

Tom Rini Aug. 28, 2014, 9:16 p.m. | #1
On Thu, Aug 28, 2014 at 10:53:51AM -0700, Steve Rae wrote:

> Add original file (pristine) from :
>   https://www.codeaurora.org/cgit/quic/la/kernel/lk/plain/app/aboot/aboot.c?h=master
> [3b5092d20bd15a7a2879c13e9f64acc48d04af2d]
> 
> Signed-off-by: Steve Rae <srae@broadcom.com>

OK, let us back the truck up, so to speak.  This particular version of
the file has an odd license.  Looking at
https://android.googlesource.com/kernel/lk/+/master/app/aboot/aboot.c
[54963a727d3e4ed1e945c7ec012b5cc5de168ac5] and it has the normal
BSD-3-Clause text.  Lets grab and adapt that so we can drop the license
issue.
Steve Rae Aug. 28, 2014, 9:31 p.m. | #2
On 14-08-28 02:16 PM, Tom Rini wrote:
> On Thu, Aug 28, 2014 at 10:53:51AM -0700, Steve Rae wrote:
>
>> Add original file (pristine) from :
>>    https://www.codeaurora.org/cgit/quic/la/kernel/lk/plain/app/aboot/aboot.c?h=master
>> [3b5092d20bd15a7a2879c13e9f64acc48d04af2d]
>>
>> Signed-off-by: Steve Rae <srae@broadcom.com>
>
> OK, let us back the truck up, so to speak.  This particular version of
> the file has an odd license.  Looking at
> https://android.googlesource.com/kernel/lk/+/master/app/aboot/aboot.c
> [54963a727d3e4ed1e945c7ec012b5cc5de168ac5] and it has the normal
> BSD-3-Clause text.  Lets grab and adapt that so we can drop the license
> issue.
>

OK -- "v3" coming soon!
Steve Rae Aug. 28, 2014, 9:52 p.m. | #3
On 14-08-28 02:31 PM, Steve Rae wrote:
>
> On 14-08-28 02:16 PM, Tom Rini wrote:
>> On Thu, Aug 28, 2014 at 10:53:51AM -0700, Steve Rae wrote:
>>
>>> Add original file (pristine) from :
>>>
>>> https://www.codeaurora.org/cgit/quic/la/kernel/lk/plain/app/aboot/aboot.c?h=master
>>>
>>> [3b5092d20bd15a7a2879c13e9f64acc48d04af2d]
>>>
>>> Signed-off-by: Steve Rae <srae@broadcom.com>
>>
>> OK, let us back the truck up, so to speak.  This particular version of
>> the file has an odd license.  Looking at
>> https://android.googlesource.com/kernel/lk/+/master/app/aboot/aboot.c
>> [54963a727d3e4ed1e945c7ec012b5cc5de168ac5] and it has the normal
>> BSD-3-Clause text.  Lets grab and adapt that so we can drop the license
>> issue.
>>
>
> OK -- "v3" coming soon!

OOPS! -- this "aboot.c" does not contain the support for the "sparse 
image format" -- I cannot use this file!
Sorry....
Marek Vasut Aug. 29, 2014, 8:20 a.m. | #4
On Thursday, August 28, 2014 at 11:52:40 PM, Steve Rae wrote:
> On 14-08-28 02:31 PM, Steve Rae wrote:
> > On 14-08-28 02:16 PM, Tom Rini wrote:
> >> On Thu, Aug 28, 2014 at 10:53:51AM -0700, Steve Rae wrote:
> >>> Add original file (pristine) from :
> >>> 
> >>> https://www.codeaurora.org/cgit/quic/la/kernel/lk/plain/app/aboot/aboot
> >>> .c?h=master
> >>> 
> >>> [3b5092d20bd15a7a2879c13e9f64acc48d04af2d]
> >>> 
> >>> Signed-off-by: Steve Rae <srae@broadcom.com>
> >> 
> >> OK, let us back the truck up, so to speak.  This particular version of
> >> the file has an odd license.  Looking at
> >> https://android.googlesource.com/kernel/lk/+/master/app/aboot/aboot.c
> >> [54963a727d3e4ed1e945c7ec012b5cc5de168ac5] and it has the normal
> >> BSD-3-Clause text.  Lets grab and adapt that so we can drop the license
> >> issue.
> > 
> > OK -- "v3" coming soon!
> 
> OOPS! -- this "aboot.c" does not contain the support for the "sparse
> image format" -- I cannot use this file!
> Sorry....

Oh, but you can implement that part into the file with a subsequent patch, no ?

Best regards,
Marek Vasut
Tom Rini Aug. 29, 2014, 3:11 p.m. | #5
On Thu, Aug 28, 2014 at 02:52:40PM -0700, Steve Rae wrote:
> 
> On 14-08-28 02:31 PM, Steve Rae wrote:
> >
> >On 14-08-28 02:16 PM, Tom Rini wrote:
> >>On Thu, Aug 28, 2014 at 10:53:51AM -0700, Steve Rae wrote:
> >>
> >>>Add original file (pristine) from :
> >>>
> >>>https://www.codeaurora.org/cgit/quic/la/kernel/lk/plain/app/aboot/aboot.c?h=master
> >>>
> >>>[3b5092d20bd15a7a2879c13e9f64acc48d04af2d]
> >>>
> >>>Signed-off-by: Steve Rae <srae@broadcom.com>
> >>
> >>OK, let us back the truck up, so to speak.  This particular version of
> >>the file has an odd license.  Looking at
> >>https://android.googlesource.com/kernel/lk/+/master/app/aboot/aboot.c
> >>[54963a727d3e4ed1e945c7ec012b5cc5de168ac5] and it has the normal
> >>BSD-3-Clause text.  Lets grab and adapt that so we can drop the license
> >>issue.
> >>
> >
> >OK -- "v3" coming soon!
> 
> OOPS! -- this "aboot.c" does not contain the support for the "sparse
> image format" -- I cannot use this file!

Can you poke around more for a version of aboot.c that has sparse image
support and comes more directly from google.com and thus hopefully
someone caught the rather strange license text changes?
Steve Rae Aug. 29, 2014, 5:38 p.m. | #6
On 14-08-29 08:11 AM, Tom Rini wrote:
> On Thu, Aug 28, 2014 at 02:52:40PM -0700, Steve Rae wrote:
>>
>> On 14-08-28 02:31 PM, Steve Rae wrote:
>>>
>>> On 14-08-28 02:16 PM, Tom Rini wrote:
>>>> On Thu, Aug 28, 2014 at 10:53:51AM -0700, Steve Rae wrote:
>>>>
>>>>> Add original file (pristine) from :
>>>>>
>>>>> https://www.codeaurora.org/cgit/quic/la/kernel/lk/plain/app/aboot/aboot.c?h=master
>>>>>
>>>>> [3b5092d20bd15a7a2879c13e9f64acc48d04af2d]
>>>>>
>>>>> Signed-off-by: Steve Rae <srae@broadcom.com>
>>>>
>>>> OK, let us back the truck up, so to speak.  This particular version of
>>>> the file has an odd license.  Looking at
>>>> https://android.googlesource.com/kernel/lk/+/master/app/aboot/aboot.c
>>>> [54963a727d3e4ed1e945c7ec012b5cc5de168ac5] and it has the normal
>>>> BSD-3-Clause text.  Lets grab and adapt that so we can drop the license
>>>> issue.
>>>>
>>>
>>> OK -- "v3" coming soon!
>>
>> OOPS! -- this "aboot.c" does not contain the support for the "sparse
>> image format" -- I cannot use this file!
>
> Can you poke around more for a version of aboot.c that has sparse image
> support and comes more directly from google.com and thus hopefully
> someone caught the rather strange license text changes?
>
I have previously spent hours looking for:
(1) sparse_format.h -- which we now have (thanks to Colin Cross)
(2) any implementation of the "while()" loop which parses this "sparse 
format"
This implementation, in aboot.c (also recommended by Colin Cross), is 
also available from "Code Aurora" -- but it has the same wording as the 
"Linux Foundation" file; I have not found it anywhere else.
I cannot spend any more time on this license issue....
Please keep me informed of the outcome!
Thanks, Steve
Marek Vasut Aug. 29, 2014, 8:54 p.m. | #7
On Friday, August 29, 2014 at 07:38:39 PM, Steve Rae wrote:
> On 14-08-29 08:11 AM, Tom Rini wrote:
> > On Thu, Aug 28, 2014 at 02:52:40PM -0700, Steve Rae wrote:
> >> On 14-08-28 02:31 PM, Steve Rae wrote:
> >>> On 14-08-28 02:16 PM, Tom Rini wrote:
> >>>> On Thu, Aug 28, 2014 at 10:53:51AM -0700, Steve Rae wrote:
> >>>>> Add original file (pristine) from :
> >>>>> 
> >>>>> https://www.codeaurora.org/cgit/quic/la/kernel/lk/plain/app/aboot/abo
> >>>>> ot.c?h=master
> >>>>> 
> >>>>> [3b5092d20bd15a7a2879c13e9f64acc48d04af2d]
> >>>>> 
> >>>>> Signed-off-by: Steve Rae <srae@broadcom.com>
> >>>> 
> >>>> OK, let us back the truck up, so to speak.  This particular version of
> >>>> the file has an odd license.  Looking at
> >>>> https://android.googlesource.com/kernel/lk/+/master/app/aboot/aboot.c
> >>>> [54963a727d3e4ed1e945c7ec012b5cc5de168ac5] and it has the normal
> >>>> BSD-3-Clause text.  Lets grab and adapt that so we can drop the
> >>>> license issue.
> >>> 
> >>> OK -- "v3" coming soon!
> >> 
> >> OOPS! -- this "aboot.c" does not contain the support for the "sparse
> >> image format" -- I cannot use this file!
> > 
> > Can you poke around more for a version of aboot.c that has sparse image
> > support and comes more directly from google.com and thus hopefully
> > someone caught the rather strange license text changes?
> 
> I have previously spent hours looking for:
> (1) sparse_format.h -- which we now have (thanks to Colin Cross)
> (2) any implementation of the "while()" loop which parses this "sparse
> format"
> This implementation, in aboot.c (also recommended by Colin Cross), is
> also available from "Code Aurora" -- but it has the same wording as the
> "Linux Foundation" file; I have not found it anywhere else.
> I cannot spend any more time on this license issue....
> Please keep me informed of the outcome!

... and, this is how it ends. Again, legal crap proved to be a death sentence 
for a patch and carried with it an excessive amount of wasted effort.

Best regards,
Marek Vasut
Steve Rae Aug. 29, 2014, 11:13 p.m. | #8
On 14-08-29 01:54 PM, Marek Vasut wrote:
> On Friday, August 29, 2014 at 07:38:39 PM, Steve Rae wrote:
>> On 14-08-29 08:11 AM, Tom Rini wrote:
>>> On Thu, Aug 28, 2014 at 02:52:40PM -0700, Steve Rae wrote:
>>>> On 14-08-28 02:31 PM, Steve Rae wrote:
>>>>> On 14-08-28 02:16 PM, Tom Rini wrote:
>>>>>> On Thu, Aug 28, 2014 at 10:53:51AM -0700, Steve Rae wrote:
>>>>>>> Add original file (pristine) from :
>>>>>>>
>>>>>>> https://www.codeaurora.org/cgit/quic/la/kernel/lk/plain/app/aboot/abo
>>>>>>> ot.c?h=master
>>>>>>>
>>>>>>> [3b5092d20bd15a7a2879c13e9f64acc48d04af2d]
>>>>>>>
>>>>>>> Signed-off-by: Steve Rae <srae@broadcom.com>
>>>>>>
>>>>>> OK, let us back the truck up, so to speak.  This particular version of
>>>>>> the file has an odd license.  Looking at
>>>>>> https://android.googlesource.com/kernel/lk/+/master/app/aboot/aboot.c
>>>>>> [54963a727d3e4ed1e945c7ec012b5cc5de168ac5] and it has the normal
>>>>>> BSD-3-Clause text.  Lets grab and adapt that so we can drop the
>>>>>> license issue.
>>>>>
>>>>> OK -- "v3" coming soon!
>>>>
>>>> OOPS! -- this "aboot.c" does not contain the support for the "sparse
>>>> image format" -- I cannot use this file!
>>>
>>> Can you poke around more for a version of aboot.c that has sparse image
>>> support and comes more directly from google.com and thus hopefully
>>> someone caught the rather strange license text changes?
>>
>> I have previously spent hours looking for:
>> (1) sparse_format.h -- which we now have (thanks to Colin Cross)
>> (2) any implementation of the "while()" loop which parses this "sparse
>> format"
>> This implementation, in aboot.c (also recommended by Colin Cross), is
>> also available from "Code Aurora" -- but it has the same wording as the
>> "Linux Foundation" file; I have not found it anywhere else.
>> I cannot spend any more time on this license issue....
>> Please keep me informed of the outcome!
>
> ... and, this is how it ends. Again, legal crap proved to be a death sentence
> for a patch and carried with it an excessive amount of wasted effort.
>
> Best regards,
> Marek Vasut
>

I certainly hope not 100% dead!!!!
If U-Boot would accept (the currently one-off) BSD-3L-Clause, then this 
could live!
Thanks, Steve
Steve Rae Sept. 3, 2014, 12:03 a.m. | #9
On 14-08-29 04:13 PM, Steve Rae wrote:
>
>
> On 14-08-29 01:54 PM, Marek Vasut wrote:
>> On Friday, August 29, 2014 at 07:38:39 PM, Steve Rae wrote:
>>> On 14-08-29 08:11 AM, Tom Rini wrote:
>>>> On Thu, Aug 28, 2014 at 02:52:40PM -0700, Steve Rae wrote:
>>>>> On 14-08-28 02:31 PM, Steve Rae wrote:
>>>>>> On 14-08-28 02:16 PM, Tom Rini wrote:
>>>>>>> On Thu, Aug 28, 2014 at 10:53:51AM -0700, Steve Rae wrote:
>>>>>>>> Add original file (pristine) from :
>>>>>>>>
>>>>>>>> https://www.codeaurora.org/cgit/quic/la/kernel/lk/plain/app/aboot/abo
>>>>>>>>
>>>>>>>> ot.c?h=master
>>>>>>>>
>>>>>>>> [3b5092d20bd15a7a2879c13e9f64acc48d04af2d]
>>>>>>>>
>>>>>>>> Signed-off-by: Steve Rae <srae@broadcom.com>
>>>>>>>
>>>>>>> OK, let us back the truck up, so to speak.  This particular
>>>>>>> version of
>>>>>>> the file has an odd license.  Looking at
>>>>>>> https://android.googlesource.com/kernel/lk/+/master/app/aboot/aboot.c
>>>>>>>
>>>>>>> [54963a727d3e4ed1e945c7ec012b5cc5de168ac5] and it has the normal
>>>>>>> BSD-3-Clause text.  Lets grab and adapt that so we can drop the
>>>>>>> license issue.
>>>>>>
>>>>>> OK -- "v3" coming soon!
>>>>>
>>>>> OOPS! -- this "aboot.c" does not contain the support for the "sparse
>>>>> image format" -- I cannot use this file!
>>>>
>>>> Can you poke around more for a version of aboot.c that has sparse image
>>>> support and comes more directly from google.com and thus hopefully
>>>> someone caught the rather strange license text changes?
>>>
>>> I have previously spent hours looking for:
>>> (1) sparse_format.h -- which we now have (thanks to Colin Cross)
>>> (2) any implementation of the "while()" loop which parses this "sparse
>>> format"
>>> This implementation, in aboot.c (also recommended by Colin Cross), is
>>> also available from "Code Aurora" -- but it has the same wording as the
>>> "Linux Foundation" file; I have not found it anywhere else.
>>> I cannot spend any more time on this license issue....
>>> Please keep me informed of the outcome!
>>
>> ... and, this is how it ends. Again, legal crap proved to be a death
>> sentence
>> for a patch and carried with it an excessive amount of wasted effort.
>>
>> Best regards,
>> Marek Vasut
>>
>
> I certainly hope not 100% dead!!!!
> If U-Boot would accept (the currently one-off) BSD-3L-Clause, then this
> could live!
> Thanks, Steve

Any progress on the license wording?

(1) create BSD-3L-Clause
or
(2) leave the original text in place, and add the following:
  * NOTE:
  *   Although it is very similar, this license text is not identical
  *   to the "BSD-3-Clause", therefore, DO NOT MODIFY THIS LICENSE TEXT!
or
(3) ???

Please let me know!
Thanks, Steve
Tom Rini Sept. 3, 2014, 12:33 a.m. | #10
On Tue, Sep 02, 2014 at 05:03:53PM -0700, Steve Rae wrote:
> 
> 
> On 14-08-29 04:13 PM, Steve Rae wrote:
> >
> >
> >On 14-08-29 01:54 PM, Marek Vasut wrote:
> >>On Friday, August 29, 2014 at 07:38:39 PM, Steve Rae wrote:
> >>>On 14-08-29 08:11 AM, Tom Rini wrote:
> >>>>On Thu, Aug 28, 2014 at 02:52:40PM -0700, Steve Rae wrote:
> >>>>>On 14-08-28 02:31 PM, Steve Rae wrote:
> >>>>>>On 14-08-28 02:16 PM, Tom Rini wrote:
> >>>>>>>On Thu, Aug 28, 2014 at 10:53:51AM -0700, Steve Rae wrote:
> >>>>>>>>Add original file (pristine) from :
> >>>>>>>>
> >>>>>>>>https://www.codeaurora.org/cgit/quic/la/kernel/lk/plain/app/aboot/abo
> >>>>>>>>
> >>>>>>>>ot.c?h=master
> >>>>>>>>
> >>>>>>>>[3b5092d20bd15a7a2879c13e9f64acc48d04af2d]
> >>>>>>>>
> >>>>>>>>Signed-off-by: Steve Rae <srae@broadcom.com>
> >>>>>>>
> >>>>>>>OK, let us back the truck up, so to speak.  This particular
> >>>>>>>version of
> >>>>>>>the file has an odd license.  Looking at
> >>>>>>>https://android.googlesource.com/kernel/lk/+/master/app/aboot/aboot.c
> >>>>>>>
> >>>>>>>[54963a727d3e4ed1e945c7ec012b5cc5de168ac5] and it has the normal
> >>>>>>>BSD-3-Clause text.  Lets grab and adapt that so we can drop the
> >>>>>>>license issue.
> >>>>>>
> >>>>>>OK -- "v3" coming soon!
> >>>>>
> >>>>>OOPS! -- this "aboot.c" does not contain the support for the "sparse
> >>>>>image format" -- I cannot use this file!
> >>>>
> >>>>Can you poke around more for a version of aboot.c that has sparse image
> >>>>support and comes more directly from google.com and thus hopefully
> >>>>someone caught the rather strange license text changes?
> >>>
> >>>I have previously spent hours looking for:
> >>>(1) sparse_format.h -- which we now have (thanks to Colin Cross)
> >>>(2) any implementation of the "while()" loop which parses this "sparse
> >>>format"
> >>>This implementation, in aboot.c (also recommended by Colin Cross), is
> >>>also available from "Code Aurora" -- but it has the same wording as the
> >>>"Linux Foundation" file; I have not found it anywhere else.
> >>>I cannot spend any more time on this license issue....
> >>>Please keep me informed of the outcome!
> >>
> >>... and, this is how it ends. Again, legal crap proved to be a death
> >>sentence
> >>for a patch and carried with it an excessive amount of wasted effort.
> >>
> >>Best regards,
> >>Marek Vasut
> >>
> >
> >I certainly hope not 100% dead!!!!
> >If U-Boot would accept (the currently one-off) BSD-3L-Clause, then this
> >could live!
> >Thanks, Steve
> 
> Any progress on the license wording?
> 
> (1) create BSD-3L-Clause
> or
> (2) leave the original text in place, and add the following:
>  * NOTE:
>  *   Although it is very similar, this license text is not identical
>  *   to the "BSD-3-Clause", therefore, DO NOT MODIFY THIS LICENSE TEXT!

#2 please, thanks.

Patch

diff --git a/common/aboot.c b/common/aboot.c
new file mode 100644
index 0000000..3b5092d
--- /dev/null
+++ b/common/aboot.c
@@ -0,0 +1,2643 @@ 
+/*
+ * Copyright (c) 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Copyright (c) 2009-2014, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of The Linux Foundation nor
+ *       the names of its contributors may be used to endorse or promote
+ *       products derived from this software without specific prior written
+ *       permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <app.h>
+#include <debug.h>
+#include <arch/arm.h>
+#include <string.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <kernel/thread.h>
+#include <arch/ops.h>
+
+#include <dev/flash.h>
+#include <lib/ptable.h>
+#include <dev/keys.h>
+#include <dev/fbcon.h>
+#include <baseband.h>
+#include <target.h>
+#include <mmc.h>
+#include <partition_parser.h>
+#include <platform.h>
+#include <crypto_hash.h>
+#include <malloc.h>
+#include <boot_stats.h>
+#include <sha.h>
+#include <platform/iomap.h>
+#include <boot_device.h>
+
+#if DEVICE_TREE
+#include <libfdt.h>
+#include <dev_tree.h>
+#endif
+
+#include "image_verify.h"
+#include "recovery.h"
+#include "bootimg.h"
+#include "fastboot.h"
+#include "sparse_format.h"
+#include "mmc.h"
+#include "devinfo.h"
+#include "board.h"
+#include "scm.h"
+
+extern  bool target_use_signed_kernel(void);
+extern void platform_uninit(void);
+extern void target_uninit(void);
+extern int get_target_boot_params(const char *cmdline, const char *part,
+				  char *buf, int buflen);
+
+void write_device_info_mmc(device_info *dev);
+void write_device_info_flash(device_info *dev);
+
+#define EXPAND(NAME) #NAME
+#define TARGET(NAME) EXPAND(NAME)
+
+#ifdef MEMBASE
+#define EMMC_BOOT_IMG_HEADER_ADDR (0xFF000+(MEMBASE))
+#else
+#define EMMC_BOOT_IMG_HEADER_ADDR 0xFF000
+#endif
+
+#ifndef MEMSIZE
+#define MEMSIZE 1024*1024
+#endif
+
+#define MAX_TAGS_SIZE   1024
+
+#define RECOVERY_MODE   0x77665502
+#define FASTBOOT_MODE   0x77665500
+
+/* make 4096 as default size to ensure EFS,EXT4's erasing */
+#define DEFAULT_ERASE_SIZE  4096
+#define MAX_PANEL_BUF_SIZE 128
+
+#define UBI_MAGIC      "UBI#"
+#define DISPLAY_DEFAULT_PREFIX "mdss_mdp"
+#define UBI_MAGIC_SIZE 0x04
+#define BOOT_DEV_MAX_LEN  64
+
+#define IS_ARM64(ptr) (ptr->magic_64 == KERNEL64_HDR_MAGIC) ? true : false
+
+#define ADD_OF(a, b) (UINT_MAX - b > a) ? (a + b) : UINT_MAX
+
+#if UFS_SUPPORT
+static const char *emmc_cmdline = " androidboot.bootdevice=";
+#else
+static const char *emmc_cmdline = " androidboot.emmc=true";
+#endif
+static const char *usb_sn_cmdline = " androidboot.serialno=";
+static const char *androidboot_mode = " androidboot.mode=";
+static const char *loglevel         = " quiet";
+static const char *battchg_pause = " androidboot.mode=charger";
+static const char *auth_kernel = " androidboot.authorized_kernel=true";
+static const char *secondary_gpt_enable = " gpt";
+
+static const char *baseband_apq     = " androidboot.baseband=apq";
+static const char *baseband_msm     = " androidboot.baseband=msm";
+static const char *baseband_csfb    = " androidboot.baseband=csfb";
+static const char *baseband_svlte2a = " androidboot.baseband=svlte2a";
+static const char *baseband_mdm     = " androidboot.baseband=mdm";
+static const char *baseband_mdm2    = " androidboot.baseband=mdm2";
+static const char *baseband_sglte   = " androidboot.baseband=sglte";
+static const char *baseband_dsda    = " androidboot.baseband=dsda";
+static const char *baseband_dsda2   = " androidboot.baseband=dsda2";
+static const char *baseband_sglte2  = " androidboot.baseband=sglte2";
+static const char *warmboot_cmdline = " qpnp-power-on.warm_boot=1";
+
+static unsigned page_size = 0;
+static unsigned page_mask = 0;
+static char ffbm_mode_string[FFBM_MODE_BUF_SIZE];
+static bool boot_into_ffbm;
+static char target_boot_params[64];
+
+/* Assuming unauthorized kernel image by default */
+static int auth_kernel_img = 0;
+
+static device_info device = {DEVICE_MAGIC, 0, 0, 0, 0};
+
+struct atag_ptbl_entry
+{
+	char name[16];
+	unsigned offset;
+	unsigned size;
+	unsigned flags;
+};
+
+/*
+ * Partition info, required to be published
+ * for fastboot
+ */
+struct getvar_partition_info {
+	const char part_name[MAX_GPT_NAME_SIZE]; /* Partition name */
+	char getvar_size[MAX_GET_VAR_NAME_SIZE]; /* fastboot get var name for size */
+	char getvar_type[MAX_GET_VAR_NAME_SIZE]; /* fastboot get var name for type */
+	char size_response[MAX_RSP_SIZE];        /* fastboot response for size */
+	char type_response[MAX_RSP_SIZE];        /* fastboot response for type */
+};
+
+/*
+ * Right now, we are publishing the info for only
+ * three partitions
+ */
+struct getvar_partition_info part_info[] =
+{
+	{ "system"  , "partition-size:", "partition-type:", "", "ext4" },
+	{ "userdata", "partition-size:", "partition-type:", "", "ext4" },
+	{ "cache"   , "partition-size:", "partition-type:", "", "ext4" },
+};
+
+char max_download_size[MAX_RSP_SIZE];
+char charger_screen_enabled[MAX_RSP_SIZE];
+char sn_buf[13];
+char display_panel_buf[MAX_PANEL_BUF_SIZE];
+char panel_display_mode[MAX_RSP_SIZE];
+
+extern int emmc_recovery_init(void);
+
+#if NO_KEYPAD_DRIVER
+extern int fastboot_trigger(void);
+#endif
+
+static void update_ker_tags_rdisk_addr(struct boot_img_hdr *hdr, bool is_arm64)
+{
+	/* overwrite the destination of specified for the project */
+#ifdef ABOOT_IGNORE_BOOT_HEADER_ADDRS
+	if (is_arm64)
+		hdr->kernel_addr = ABOOT_FORCE_KERNEL64_ADDR;
+	else
+		hdr->kernel_addr = ABOOT_FORCE_KERNEL_ADDR;
+	hdr->ramdisk_addr = ABOOT_FORCE_RAMDISK_ADDR;
+	hdr->tags_addr = ABOOT_FORCE_TAGS_ADDR;
+#endif
+}
+
+static void ptentry_to_tag(unsigned **ptr, struct ptentry *ptn)
+{
+	struct atag_ptbl_entry atag_ptn;
+
+	memcpy(atag_ptn.name, ptn->name, 16);
+	atag_ptn.name[15] = '\0';
+	atag_ptn.offset = ptn->start;
+	atag_ptn.size = ptn->length;
+	atag_ptn.flags = ptn->flags;
+	memcpy(*ptr, &atag_ptn, sizeof(struct atag_ptbl_entry));
+	*ptr += sizeof(struct atag_ptbl_entry) / sizeof(unsigned);
+}
+
+unsigned char *update_cmdline(const char * cmdline)
+{
+	int cmdline_len = 0;
+	int have_cmdline = 0;
+	unsigned char *cmdline_final = NULL;
+	int pause_at_bootup = 0;
+	bool warm_boot = false;
+	bool gpt_exists = partition_gpt_exists();
+	int have_target_boot_params = 0;
+	char *boot_dev_buf = NULL;
+
+	if (cmdline && cmdline[0]) {
+		cmdline_len = strlen(cmdline);
+		have_cmdline = 1;
+	}
+	if (target_is_emmc_boot()) {
+		cmdline_len += strlen(emmc_cmdline);
+#if UFS_SUPPORT
+		boot_dev_buf = (char *) malloc(sizeof(char) * BOOT_DEV_MAX_LEN);
+		ASSERT(boot_dev_buf);
+		platform_boot_dev_cmdline(boot_dev_buf);
+		cmdline_len += strlen(boot_dev_buf);
+#endif
+	}
+
+	cmdline_len += strlen(usb_sn_cmdline);
+	cmdline_len += strlen(sn_buf);
+
+	if (boot_into_recovery && gpt_exists)
+		cmdline_len += strlen(secondary_gpt_enable);
+
+	if (boot_into_ffbm) {
+		cmdline_len += strlen(androidboot_mode);
+		cmdline_len += strlen(ffbm_mode_string);
+		/* reduce kernel console messages to speed-up boot */
+		cmdline_len += strlen(loglevel);
+	} else if (device.charger_screen_enabled &&
+			target_pause_for_battery_charge()) {
+		pause_at_bootup = 1;
+		cmdline_len += strlen(battchg_pause);
+	}
+
+	if(target_use_signed_kernel() && auth_kernel_img) {
+		cmdline_len += strlen(auth_kernel);
+	}
+
+	if (get_target_boot_params(cmdline, boot_into_recovery ? "recoveryfs" :
+								 "system",
+				   target_boot_params,
+				   sizeof(target_boot_params)) == 0) {
+		have_target_boot_params = 1;
+		cmdline_len += strlen(target_boot_params);
+	}
+
+	/* Determine correct androidboot.baseband to use */
+	switch(target_baseband())
+	{
+		case BASEBAND_APQ:
+			cmdline_len += strlen(baseband_apq);
+			break;
+
+		case BASEBAND_MSM:
+			cmdline_len += strlen(baseband_msm);
+			break;
+
+		case BASEBAND_CSFB:
+			cmdline_len += strlen(baseband_csfb);
+			break;
+
+		case BASEBAND_SVLTE2A:
+			cmdline_len += strlen(baseband_svlte2a);
+			break;
+
+		case BASEBAND_MDM:
+			cmdline_len += strlen(baseband_mdm);
+			break;
+
+		case BASEBAND_MDM2:
+			cmdline_len += strlen(baseband_mdm2);
+			break;
+
+		case BASEBAND_SGLTE:
+			cmdline_len += strlen(baseband_sglte);
+			break;
+
+		case BASEBAND_SGLTE2:
+			cmdline_len += strlen(baseband_sglte2);
+			break;
+
+		case BASEBAND_DSDA:
+			cmdline_len += strlen(baseband_dsda);
+			break;
+
+		case BASEBAND_DSDA2:
+			cmdline_len += strlen(baseband_dsda2);
+			break;
+	}
+
+	if (cmdline) {
+		if ((strstr(cmdline, DISPLAY_DEFAULT_PREFIX) == NULL) &&
+			target_display_panel_node(device.display_panel,
+			display_panel_buf, MAX_PANEL_BUF_SIZE) &&
+			strlen(display_panel_buf)) {
+			cmdline_len += strlen(display_panel_buf);
+		}
+	}
+
+	if (target_warm_boot()) {
+		warm_boot = true;
+		cmdline_len += strlen(warmboot_cmdline);
+	}
+
+	if (cmdline_len > 0) {
+		const char *src;
+		unsigned char *dst = (unsigned char*) malloc((cmdline_len + 4) & (~3));
+		ASSERT(dst != NULL);
+
+		/* Save start ptr for debug print */
+		cmdline_final = dst;
+		if (have_cmdline) {
+			src = cmdline;
+			while ((*dst++ = *src++));
+		}
+		if (target_is_emmc_boot()) {
+			src = emmc_cmdline;
+			if (have_cmdline) --dst;
+			have_cmdline = 1;
+			while ((*dst++ = *src++));
+#if UFS_SUPPORT
+			src = boot_dev_buf;
+			if (have_cmdline) --dst;
+			while ((*dst++ = *src++));
+#endif
+		}
+
+		src = usb_sn_cmdline;
+		if (have_cmdline) --dst;
+		have_cmdline = 1;
+		while ((*dst++ = *src++));
+		src = sn_buf;
+		if (have_cmdline) --dst;
+		have_cmdline = 1;
+		while ((*dst++ = *src++));
+		if (warm_boot) {
+			if (have_cmdline) --dst;
+			src = warmboot_cmdline;
+			while ((*dst++ = *src++));
+		}
+
+		if (boot_into_recovery && gpt_exists) {
+			src = secondary_gpt_enable;
+			if (have_cmdline) --dst;
+			while ((*dst++ = *src++));
+		}
+
+		if (boot_into_ffbm) {
+			src = androidboot_mode;
+			if (have_cmdline) --dst;
+			while ((*dst++ = *src++));
+			src = ffbm_mode_string;
+			if (have_cmdline) --dst;
+			while ((*dst++ = *src++));
+			src = loglevel;
+			if (have_cmdline) --dst;
+			while ((*dst++ = *src++));
+		} else if (pause_at_bootup) {
+			src = battchg_pause;
+			if (have_cmdline) --dst;
+			while ((*dst++ = *src++));
+		}
+
+		if(target_use_signed_kernel() && auth_kernel_img) {
+			src = auth_kernel;
+			if (have_cmdline) --dst;
+			while ((*dst++ = *src++));
+		}
+
+		switch(target_baseband())
+		{
+			case BASEBAND_APQ:
+				src = baseband_apq;
+				if (have_cmdline) --dst;
+				while ((*dst++ = *src++));
+				break;
+
+			case BASEBAND_MSM:
+				src = baseband_msm;
+				if (have_cmdline) --dst;
+				while ((*dst++ = *src++));
+				break;
+
+			case BASEBAND_CSFB:
+				src = baseband_csfb;
+				if (have_cmdline) --dst;
+				while ((*dst++ = *src++));
+				break;
+
+			case BASEBAND_SVLTE2A:
+				src = baseband_svlte2a;
+				if (have_cmdline) --dst;
+				while ((*dst++ = *src++));
+				break;
+
+			case BASEBAND_MDM:
+				src = baseband_mdm;
+				if (have_cmdline) --dst;
+				while ((*dst++ = *src++));
+				break;
+
+			case BASEBAND_MDM2:
+				src = baseband_mdm2;
+				if (have_cmdline) --dst;
+				while ((*dst++ = *src++));
+				break;
+
+			case BASEBAND_SGLTE:
+				src = baseband_sglte;
+				if (have_cmdline) --dst;
+				while ((*dst++ = *src++));
+				break;
+
+			case BASEBAND_SGLTE2:
+				src = baseband_sglte2;
+				if (have_cmdline) --dst;
+				while ((*dst++ = *src++));
+				break;
+
+			case BASEBAND_DSDA:
+				src = baseband_dsda;
+				if (have_cmdline) --dst;
+				while ((*dst++ = *src++));
+				break;
+
+			case BASEBAND_DSDA2:
+				src = baseband_dsda2;
+				if (have_cmdline) --dst;
+				while ((*dst++ = *src++));
+				break;
+		}
+
+		if (strlen(display_panel_buf)) {
+			src = display_panel_buf;
+			if (have_cmdline) --dst;
+			while ((*dst++ = *src++));
+		}
+
+		if (have_target_boot_params) {
+			if (have_cmdline) --dst;
+			src = target_boot_params;
+			while ((*dst++ = *src++));
+		}
+	}
+
+
+	if (boot_dev_buf)
+		free(boot_dev_buf);
+
+	dprintf(INFO, "cmdline: %s\n", cmdline_final);
+	return cmdline_final;
+}
+
+unsigned *atag_core(unsigned *ptr)
+{
+	/* CORE */
+	*ptr++ = 2;
+	*ptr++ = 0x54410001;
+
+	return ptr;
+
+}
+
+unsigned *atag_ramdisk(unsigned *ptr, void *ramdisk,
+							   unsigned ramdisk_size)
+{
+	if (ramdisk_size) {
+		*ptr++ = 4;
+		*ptr++ = 0x54420005;
+		*ptr++ = (unsigned)ramdisk;
+		*ptr++ = ramdisk_size;
+	}
+
+	return ptr;
+}
+
+unsigned *atag_ptable(unsigned **ptr_addr)
+{
+	int i;
+	struct ptable *ptable;
+
+	if ((ptable = flash_get_ptable()) && (ptable->count != 0)) {
+		*(*ptr_addr)++ = 2 + (ptable->count * (sizeof(struct atag_ptbl_entry) /
+							sizeof(unsigned)));
+		*(*ptr_addr)++ = 0x4d534d70;
+		for (i = 0; i < ptable->count; ++i)
+			ptentry_to_tag(ptr_addr, ptable_get(ptable, i));
+	}
+
+	return (*ptr_addr);
+}
+
+unsigned *atag_cmdline(unsigned *ptr, const char *cmdline)
+{
+	int cmdline_length = 0;
+	int n;
+	char *dest;
+
+	cmdline_length = strlen((const char*)cmdline);
+	n = (cmdline_length + 4) & (~3);
+
+	*ptr++ = (n / 4) + 2;
+	*ptr++ = 0x54410009;
+	dest = (char *) ptr;
+	while ((*dest++ = *cmdline++));
+	ptr += (n / 4);
+
+	return ptr;
+}
+
+unsigned *atag_end(unsigned *ptr)
+{
+	/* END */
+	*ptr++ = 0;
+	*ptr++ = 0;
+
+	return ptr;
+}
+
+void generate_atags(unsigned *ptr, const char *cmdline,
+                    void *ramdisk, unsigned ramdisk_size)
+{
+
+	ptr = atag_core(ptr);
+	ptr = atag_ramdisk(ptr, ramdisk, ramdisk_size);
+	ptr = target_atag_mem(ptr);
+
+	/* Skip NAND partition ATAGS for eMMC boot */
+	if (!target_is_emmc_boot()){
+		ptr = atag_ptable(&ptr);
+	}
+
+	ptr = atag_cmdline(ptr, cmdline);
+	ptr = atag_end(ptr);
+}
+
+typedef void entry_func_ptr(unsigned, unsigned, unsigned*);
+void boot_linux(void *kernel, unsigned *tags,
+		const char *cmdline, unsigned machtype,
+		void *ramdisk, unsigned ramdisk_size)
+{
+	unsigned char *final_cmdline;
+#if DEVICE_TREE
+	int ret = 0;
+#endif
+
+	void (*entry)(unsigned, unsigned, unsigned*) = (entry_func_ptr*)(PA((addr_t)kernel));
+	uint32_t tags_phys = PA((addr_t)tags);
+	struct kernel64_hdr *kptr = (struct kernel64_hdr*)kernel;
+
+	ramdisk = PA(ramdisk);
+
+	final_cmdline = update_cmdline((const char*)cmdline);
+
+#if DEVICE_TREE
+	dprintf(INFO, "Updating device tree: start\n");
+
+	/* Update the Device Tree */
+	ret = update_device_tree((void *)tags, final_cmdline, ramdisk, ramdisk_size);
+	if(ret)
+	{
+		dprintf(CRITICAL, "ERROR: Updating Device Tree Failed \n");
+		ASSERT(0);
+	}
+	dprintf(INFO, "Updating device tree: done\n");
+#else
+	/* Generating the Atags */
+	generate_atags(tags, final_cmdline, ramdisk, ramdisk_size);
+#endif
+
+	/* Perform target specific cleanup */
+	target_uninit();
+
+	/* Turn off splash screen if enabled */
+#if DISPLAY_SPLASH_SCREEN
+	target_display_shutdown();
+#endif
+
+
+	dprintf(INFO, "booting linux @ %p, ramdisk @ %p (%d), tags/device tree @ %p\n",
+		entry, ramdisk, ramdisk_size, tags_phys);
+
+	enter_critical_section();
+
+	/* do any platform specific cleanup before kernel entry */
+	platform_uninit();
+
+	arch_disable_cache(UCACHE);
+
+#if ARM_WITH_MMU
+	arch_disable_mmu();
+#endif
+	bs_set_timestamp(BS_KERNEL_ENTRY);
+
+	if (IS_ARM64(kptr))
+		/* Jump to a 64bit kernel */
+		scm_elexec_call((paddr_t)kernel, tags_phys);
+	else
+		/* Jump to a 32bit kernel */
+		entry(0, machtype, (unsigned*)tags_phys);
+}
+
+/* Function to check if the memory address range falls within the aboot
+ * boundaries.
+ * start: Start of the memory region
+ * size: Size of the memory region
+ */
+int check_aboot_addr_range_overlap(uint32_t start, uint32_t size)
+{
+	/* Check for boundary conditions. */
+	if ((UINT_MAX - start) < size)
+		return -1;
+
+	/* Check for memory overlap. */
+	if ((start < MEMBASE) && ((start + size) <= MEMBASE))
+		return 0;
+	else if (start >= (MEMBASE + MEMSIZE))
+		return 0;
+	else
+		return -1;
+}
+
+#define ROUND_TO_PAGE(x,y) (((x) + (y)) & (~(y)))
+
+BUF_DMA_ALIGN(buf, BOOT_IMG_MAX_PAGE_SIZE); //Equal to max-supported pagesize
+#if DEVICE_TREE
+BUF_DMA_ALIGN(dt_buf, BOOT_IMG_MAX_PAGE_SIZE);
+#endif
+
+static void verify_signed_bootimg(uint32_t bootimg_addr, uint32_t bootimg_size)
+{
+	int ret;
+#if IMAGE_VERIF_ALGO_SHA1
+	uint32_t auth_algo = CRYPTO_AUTH_ALG_SHA1;
+#else
+	uint32_t auth_algo = CRYPTO_AUTH_ALG_SHA256;
+#endif
+
+	/* Assume device is rooted at this time. */
+	device.is_tampered = 1;
+
+	dprintf(INFO, "Authenticating boot image (%d): start\n", bootimg_size);
+
+	ret = image_verify((unsigned char *)bootimg_addr,
+					   (unsigned char *)(bootimg_addr + bootimg_size),
+					   bootimg_size,
+					   auth_algo);
+
+	dprintf(INFO, "Authenticating boot image: done return value = %d\n", ret);
+
+	if (ret)
+	{
+		/* Authorized kernel */
+		device.is_tampered = 0;
+		auth_kernel_img = 1;
+	}
+
+#if USE_PCOM_SECBOOT
+	set_tamper_flag(device.is_tampered);
+#endif
+
+	if(device.is_tampered)
+	{
+		write_device_info_mmc(&device);
+	#ifdef TZ_TAMPER_FUSE
+		set_tamper_fuse_cmd();
+	#endif
+	#ifdef ASSERT_ON_TAMPER
+		dprintf(CRITICAL, "Device is tampered. Asserting..\n");
+		ASSERT(0);
+	#endif
+	}
+}
+
+static bool check_format_bit()
+{
+	bool ret = false;
+	int index;
+	uint64_t offset;
+	struct boot_selection_info *in = NULL;
+	char *buf = NULL;
+
+	index = partition_get_index("bootselect");
+	if (index == INVALID_PTN)
+	{
+		dprintf(INFO, "Unable to locate /bootselect partition\n");
+		return ret;
+	}
+	offset = partition_get_offset(index);
+	if(!offset)
+	{
+		dprintf(INFO, "partition /bootselect doesn't exist\n");
+		return ret;
+	}
+	buf = (char *) memalign(CACHE_LINE, ROUNDUP(page_size, CACHE_LINE));
+	ASSERT(buf);
+	if (mmc_read(offset, (unsigned int *)buf, page_size))
+	{
+		dprintf(INFO, "mmc read failure /bootselect %d\n", page_size);
+		free(buf);
+		return ret;
+	}
+	in = (struct boot_selection_info *) buf;
+	if ((in->signature == BOOTSELECT_SIGNATURE) &&
+			(in->version == BOOTSELECT_VERSION)) {
+		if ((in->state_info & BOOTSELECT_FORMAT) &&
+				!(in->state_info & BOOTSELECT_FACTORY))
+			ret = true;
+	} else {
+		dprintf(CRITICAL, "Signature: 0x%08x or version: 0x%08x mismatched of /bootselect\n",
+				in->signature, in->version);
+		ASSERT(0);
+	}
+	free(buf);
+	return ret;
+}
+
+int boot_linux_from_mmc(void)
+{
+	struct boot_img_hdr *hdr = (void*) buf;
+	struct boot_img_hdr *uhdr;
+	unsigned offset = 0;
+	int rcode;
+	unsigned long long ptn = 0;
+	int index = INVALID_PTN;
+
+	unsigned char *image_addr = 0;
+	unsigned kernel_actual;
+	unsigned ramdisk_actual;
+	unsigned imagesize_actual;
+	unsigned second_actual = 0;
+
+#if DEVICE_TREE
+	struct dt_table *table;
+	struct dt_entry dt_entry;
+	unsigned dt_table_offset;
+	uint32_t dt_actual;
+	uint32_t dt_hdr_size;
+#endif
+	BUF_DMA_ALIGN(kbuf, BOOT_IMG_MAX_PAGE_SIZE);
+	struct kernel64_hdr *kptr = (void*) kbuf;
+
+	if (check_format_bit())
+		boot_into_recovery = 1;
+
+	if (!boot_into_recovery) {
+		memset(ffbm_mode_string, '\0', sizeof(ffbm_mode_string));
+		rcode = get_ffbm(ffbm_mode_string, sizeof(ffbm_mode_string));
+		if (rcode <= 0) {
+			boot_into_ffbm = false;
+			if (rcode < 0)
+				dprintf(CRITICAL,"failed to get ffbm cookie");
+		} else
+			boot_into_ffbm = true;
+	} else
+		boot_into_ffbm = false;
+	uhdr = (struct boot_img_hdr *)EMMC_BOOT_IMG_HEADER_ADDR;
+	if (!memcmp(uhdr->magic, BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
+		dprintf(INFO, "Unified boot method!\n");
+		hdr = uhdr;
+		goto unified_boot;
+	}
+	if (!boot_into_recovery) {
+		index = partition_get_index("boot");
+		ptn = partition_get_offset(index);
+		if(ptn == 0) {
+			dprintf(CRITICAL, "ERROR: No boot partition found\n");
+                    return -1;
+		}
+	}
+	else {
+		index = partition_get_index("recovery");
+		ptn = partition_get_offset(index);
+		if(ptn == 0) {
+			dprintf(CRITICAL, "ERROR: No recovery partition found\n");
+                    return -1;
+		}
+	}
+
+	if (mmc_read(ptn + offset, (unsigned int *) buf, page_size)) {
+		dprintf(CRITICAL, "ERROR: Cannot read boot image header\n");
+                return -1;
+	}
+
+	if (memcmp(hdr->magic, BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
+		dprintf(CRITICAL, "ERROR: Invalid boot image header\n");
+                return -1;
+	}
+
+	if (hdr->page_size && (hdr->page_size != page_size)) {
+
+		if (hdr->page_size > BOOT_IMG_MAX_PAGE_SIZE) {
+			dprintf(CRITICAL, "ERROR: Invalid page size\n");
+			return -1;
+		}
+		page_size = hdr->page_size;
+		page_mask = page_size - 1;
+	}
+
+	/* Read the next page to get kernel Image header
+	 * which lives in the second page for arm64 targets.
+	 */
+
+	if (mmc_read(ptn + page_size, (unsigned int *) kbuf, page_size)) {
+		dprintf(CRITICAL, "ERROR: Cannot read boot image header\n");
+                return -1;
+	}
+
+	/*
+	 * Update the kernel/ramdisk/tags address if the boot image header
+	 * has default values, these default values come from mkbootimg when
+	 * the boot image is flashed using fastboot flash:raw
+	 */
+	update_ker_tags_rdisk_addr(hdr, IS_ARM64(kptr));
+
+	/* Get virtual addresses since the hdr saves physical addresses. */
+	hdr->kernel_addr = VA((addr_t)(hdr->kernel_addr));
+	hdr->ramdisk_addr = VA((addr_t)(hdr->ramdisk_addr));
+	hdr->tags_addr = VA((addr_t)(hdr->tags_addr));
+
+	kernel_actual  = ROUND_TO_PAGE(hdr->kernel_size,  page_mask);
+	ramdisk_actual = ROUND_TO_PAGE(hdr->ramdisk_size, page_mask);
+
+	/* Check if the addresses in the header are valid. */
+	if (check_aboot_addr_range_overlap(hdr->kernel_addr, kernel_actual) ||
+		check_aboot_addr_range_overlap(hdr->ramdisk_addr, ramdisk_actual))
+	{
+		dprintf(CRITICAL, "kernel/ramdisk addresses overlap with aboot addresses.\n");
+		return -1;
+	}
+
+#ifndef DEVICE_TREE
+	if (check_aboot_addr_range_overlap(hdr->tags_addr, MAX_TAGS_SIZE))
+	{
+		dprintf(CRITICAL, "Tags addresses overlap with aboot addresses.\n");
+		return -1;
+	}
+#endif
+
+	/* Authenticate Kernel */
+	dprintf(INFO, "use_signed_kernel=%d, is_unlocked=%d, is_tampered=%d.\n",
+		(int) target_use_signed_kernel(),
+		device.is_unlocked,
+		device.is_tampered);
+
+	if(target_use_signed_kernel() && (!device.is_unlocked))
+	{
+		offset = 0;
+
+		image_addr = (unsigned char *)target_get_scratch_address();
+
+#if DEVICE_TREE
+		dt_actual = ROUND_TO_PAGE(hdr->dt_size, page_mask);
+		imagesize_actual = (page_size + kernel_actual + ramdisk_actual + dt_actual);
+
+		if (check_aboot_addr_range_overlap(hdr->tags_addr, dt_actual))
+		{
+			dprintf(CRITICAL, "Device tree addresses overlap with aboot addresses.\n");
+			return -1;
+		}
+#else
+		imagesize_actual = (page_size + kernel_actual + ramdisk_actual);
+
+#endif
+
+		dprintf(INFO, "Loading boot image (%d): start\n", imagesize_actual);
+		bs_set_timestamp(BS_KERNEL_LOAD_START);
+
+		if (check_aboot_addr_range_overlap(image_addr, imagesize_actual))
+		{
+			dprintf(CRITICAL, "Boot image buffer address overlaps with aboot addresses.\n");
+			return -1;
+		}
+
+		/* Read image without signature */
+		if (mmc_read(ptn + offset, (void *)image_addr, imagesize_actual))
+		{
+			dprintf(CRITICAL, "ERROR: Cannot read boot image\n");
+				return -1;
+		}
+
+		dprintf(INFO, "Loading boot image (%d): done\n", imagesize_actual);
+		bs_set_timestamp(BS_KERNEL_LOAD_DONE);
+
+		offset = imagesize_actual;
+
+		if (check_aboot_addr_range_overlap(image_addr + offset, page_size))
+		{
+			dprintf(CRITICAL, "Signature read buffer address overlaps with aboot addresses.\n");
+			return -1;
+		}
+
+		/* Read signature */
+		if(mmc_read(ptn + offset, (void *)(image_addr + offset), page_size))
+		{
+			dprintf(CRITICAL, "ERROR: Cannot read boot image signature\n");
+			return -1;
+		}
+
+		verify_signed_bootimg(image_addr, imagesize_actual);
+
+		/* Move kernel, ramdisk and device tree to correct address */
+		memmove((void*) hdr->kernel_addr, (char *)(image_addr + page_size), hdr->kernel_size);
+		memmove((void*) hdr->ramdisk_addr, (char *)(image_addr + page_size + kernel_actual), hdr->ramdisk_size);
+
+		#if DEVICE_TREE
+		if(hdr->dt_size) {
+			dt_table_offset = ((uint32_t)image_addr + page_size + kernel_actual + ramdisk_actual + second_actual);
+			table = (struct dt_table*) dt_table_offset;
+
+			if (dev_tree_validate(table, hdr->page_size, &dt_hdr_size) != 0) {
+				dprintf(CRITICAL, "ERROR: Cannot validate Device Tree Table \n");
+				return -1;
+			}
+
+			/* Find index of device tree within device tree table */
+			if(dev_tree_get_entry_info(table, &dt_entry) != 0){
+				dprintf(CRITICAL, "ERROR: Device Tree Blob cannot be found\n");
+				return -1;
+			}
+
+			/* Validate and Read device device tree in the "tags_add */
+			if (check_aboot_addr_range_overlap(hdr->tags_addr, dt_entry.size))
+			{
+				dprintf(CRITICAL, "Device tree addresses overlap with aboot addresses.\n");
+				return -1;
+			}
+
+			memmove((void *)hdr->tags_addr, (char *)dt_table_offset + dt_entry.offset, dt_entry.size);
+		} else {
+			/*
+			 * If appended dev tree is found, update the atags with
+			 * memory address to the DTB appended location on RAM.
+			 * Else update with the atags address in the kernel header
+			 */
+			void *dtb;
+			dtb = dev_tree_appended((void*) hdr->kernel_addr,
+						hdr->kernel_size,
+						(void *)hdr->tags_addr);
+			if (!dtb) {
+				dprintf(CRITICAL, "ERROR: Appended Device Tree Blob not found\n");
+				return -1;
+			}
+		}
+		#endif
+	}
+	else
+	{
+		second_actual  = ROUND_TO_PAGE(hdr->second_size,  page_mask);
+
+		dprintf(INFO, "Loading boot image (%d): start\n",
+				kernel_actual + ramdisk_actual);
+		bs_set_timestamp(BS_KERNEL_LOAD_START);
+
+		offset = page_size;
+
+		/* Load kernel */
+		if (mmc_read(ptn + offset, (void *)hdr->kernel_addr, kernel_actual)) {
+			dprintf(CRITICAL, "ERROR: Cannot read kernel image\n");
+					return -1;
+		}
+		offset += kernel_actual;
+
+		/* Load ramdisk */
+		if(ramdisk_actual != 0)
+		{
+			if (mmc_read(ptn + offset, (void *)hdr->ramdisk_addr, ramdisk_actual)) {
+				dprintf(CRITICAL, "ERROR: Cannot read ramdisk image\n");
+				return -1;
+			}
+		}
+		offset += ramdisk_actual;
+
+		dprintf(INFO, "Loading boot image (%d): done\n",
+				kernel_actual + ramdisk_actual);
+		bs_set_timestamp(BS_KERNEL_LOAD_DONE);
+
+		if(hdr->second_size != 0) {
+			offset += second_actual;
+			/* Second image loading not implemented. */
+			ASSERT(0);
+		}
+
+		#if DEVICE_TREE
+		if(hdr->dt_size != 0) {
+			/* Read the first page of device tree table into buffer */
+			if(mmc_read(ptn + offset,(unsigned int *) dt_buf, page_size)) {
+				dprintf(CRITICAL, "ERROR: Cannot read the Device Tree Table\n");
+				return -1;
+			}
+			table = (struct dt_table*) dt_buf;
+
+			if (dev_tree_validate(table, hdr->page_size, &dt_hdr_size) != 0) {
+				dprintf(CRITICAL, "ERROR: Cannot validate Device Tree Table \n");
+				return -1;
+			}
+
+			table = (struct dt_table*) memalign(CACHE_LINE, dt_hdr_size);
+			if (!table)
+				return -1;
+
+			/* Read the entire device tree table into buffer */
+			if(mmc_read(ptn + offset,(unsigned int *) table, dt_hdr_size)) {
+				dprintf(CRITICAL, "ERROR: Cannot read the Device Tree Table\n");
+				return -1;
+			}
+
+			/* Find index of device tree within device tree table */
+			if(dev_tree_get_entry_info(table, &dt_entry) != 0){
+				dprintf(CRITICAL, "ERROR: Getting device tree address failed\n");
+				return -1;
+			}
+
+			/* Validate and Read device device tree in the "tags_add */
+			if (check_aboot_addr_range_overlap(hdr->tags_addr, dt_entry.size))
+			{
+				dprintf(CRITICAL, "Device tree addresses overlap with aboot addresses.\n");
+				return -1;
+			}
+
+			if(mmc_read(ptn + offset + dt_entry.offset,
+						 (void *)hdr->tags_addr, dt_entry.size)) {
+				dprintf(CRITICAL, "ERROR: Cannot read device tree\n");
+				return -1;
+			}
+			#ifdef TZ_SAVE_KERNEL_HASH
+			aboot_save_boot_hash_mmc(hdr->kernel_addr, kernel_actual,
+				       hdr->ramdisk_addr, ramdisk_actual,
+				       ptn, offset, hdr->dt_size);
+			#endif /* TZ_SAVE_KERNEL_HASH */
+
+		} else {
+
+			/* Validate the tags_addr */
+			if (check_aboot_addr_range_overlap(hdr->tags_addr, kernel_actual))
+			{
+				dprintf(CRITICAL, "Device tree addresses overlap with aboot addresses.\n");
+				return -1;
+			}
+			/*
+			 * If appended dev tree is found, update the atags with
+			 * memory address to the DTB appended location on RAM.
+			 * Else update with the atags address in the kernel header
+			 */
+			void *dtb;
+			dtb = dev_tree_appended((void*) hdr->kernel_addr,
+						kernel_actual,
+						(void *)hdr->tags_addr);
+			if (!dtb) {
+				dprintf(CRITICAL, "ERROR: Appended Device Tree Blob not found\n");
+				return -1;
+			}
+		}
+		#endif
+	}
+
+	if (boot_into_recovery && !device.is_unlocked && !device.is_tampered)
+		target_load_ssd_keystore();
+
+unified_boot:
+
+	boot_linux((void *)hdr->kernel_addr, (void *)hdr->tags_addr,
+		   (const char *)hdr->cmdline, board_machtype(),
+		   (void *)hdr->ramdisk_addr, hdr->ramdisk_size);
+
+	return 0;
+}
+
+int boot_linux_from_flash(void)
+{
+	struct boot_img_hdr *hdr = (void*) buf;
+	struct ptentry *ptn;
+	struct ptable *ptable;
+	unsigned offset = 0;
+
+	unsigned char *image_addr = 0;
+	unsigned kernel_actual;
+	unsigned ramdisk_actual;
+	unsigned imagesize_actual;
+	unsigned second_actual;
+
+#if DEVICE_TREE
+	struct dt_table *table;
+	struct dt_entry dt_entry;
+	uint32_t dt_actual;
+	uint32_t dt_hdr_size;
+#endif
+
+	if (target_is_emmc_boot()) {
+		hdr = (struct boot_img_hdr *)EMMC_BOOT_IMG_HEADER_ADDR;
+		if (memcmp(hdr->magic, BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
+			dprintf(CRITICAL, "ERROR: Invalid boot image header\n");
+			return -1;
+		}
+		goto continue_boot;
+	}
+
+	ptable = flash_get_ptable();
+	if (ptable == NULL) {
+		dprintf(CRITICAL, "ERROR: Partition table not found\n");
+		return -1;
+	}
+
+	if(!boot_into_recovery)
+	{
+	        ptn = ptable_find(ptable, "boot");
+
+	        if (ptn == NULL) {
+		        dprintf(CRITICAL, "ERROR: No boot partition found\n");
+		        return -1;
+	        }
+	}
+	else
+	{
+	        ptn = ptable_find(ptable, "recovery");
+	        if (ptn == NULL) {
+		        dprintf(CRITICAL, "ERROR: No recovery partition found\n");
+		        return -1;
+	        }
+	}
+
+	if (flash_read(ptn, offset, buf, page_size)) {
+		dprintf(CRITICAL, "ERROR: Cannot read boot image header\n");
+		return -1;
+	}
+
+	if (memcmp(hdr->magic, BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
+		dprintf(CRITICAL, "ERROR: Invalid boot image header\n");
+		return -1;
+	}
+
+	if (hdr->page_size != page_size) {
+		dprintf(CRITICAL, "ERROR: Invalid boot image pagesize. Device pagesize: %d, Image pagesize: %d\n",page_size,hdr->page_size);
+		return -1;
+	}
+
+	/*
+	 * Update the kernel/ramdisk/tags address if the boot image header
+	 * has default values, these default values come from mkbootimg when
+	 * the boot image is flashed using fastboot flash:raw
+	 */
+	update_ker_tags_rdisk_addr(hdr, false);
+
+	/* Get virtual addresses since the hdr saves physical addresses. */
+	hdr->kernel_addr = VA((addr_t)(hdr->kernel_addr));
+	hdr->ramdisk_addr = VA((addr_t)(hdr->ramdisk_addr));
+	hdr->tags_addr = VA((addr_t)(hdr->tags_addr));
+
+	kernel_actual  = ROUND_TO_PAGE(hdr->kernel_size,  page_mask);
+	ramdisk_actual = ROUND_TO_PAGE(hdr->ramdisk_size, page_mask);
+
+	/* Check if the addresses in the header are valid. */
+	if (check_aboot_addr_range_overlap(hdr->kernel_addr, kernel_actual) ||
+		check_aboot_addr_range_overlap(hdr->ramdisk_addr, ramdisk_actual))
+	{
+		dprintf(CRITICAL, "kernel/ramdisk addresses overlap with aboot addresses.\n");
+		return -1;
+	}
+
+#ifndef DEVICE_TREE
+		if (check_aboot_addr_range_overlap(hdr->tags_addr, MAX_TAGS_SIZE))
+		{
+			dprintf(CRITICAL, "Tags addresses overlap with aboot addresses.\n");
+			return -1;
+		}
+#endif
+
+	/* Authenticate Kernel */
+	if(target_use_signed_kernel() && (!device.is_unlocked))
+	{
+		image_addr = (unsigned char *)target_get_scratch_address();
+		offset = 0;
+
+#if DEVICE_TREE
+		dt_actual = ROUND_TO_PAGE(hdr->dt_size, page_mask);
+		imagesize_actual = (page_size + kernel_actual + ramdisk_actual + dt_actual);
+
+		if (check_aboot_addr_range_overlap(hdr->tags_addr, hdr->dt_size))
+		{
+			dprintf(CRITICAL, "Device tree addresses overlap with aboot addresses.\n");
+			return -1;
+		}
+#else
+		imagesize_actual = (page_size + kernel_actual + ramdisk_actual);
+#endif
+
+		dprintf(INFO, "Loading boot image (%d): start\n", imagesize_actual);
+		bs_set_timestamp(BS_KERNEL_LOAD_START);
+
+		/* Read image without signature */
+		if (flash_read(ptn, offset, (void *)image_addr, imagesize_actual))
+		{
+			dprintf(CRITICAL, "ERROR: Cannot read boot image\n");
+				return -1;
+		}
+
+		dprintf(INFO, "Loading boot image (%d): done\n", imagesize_actual);
+		bs_set_timestamp(BS_KERNEL_LOAD_DONE);
+
+		offset = imagesize_actual;
+		/* Read signature */
+		if (flash_read(ptn, offset, (void *)(image_addr + offset), page_size))
+		{
+			dprintf(CRITICAL, "ERROR: Cannot read boot image signature\n");
+			return -1;
+		}
+
+		verify_signed_bootimg(image_addr, imagesize_actual);
+
+		/* Move kernel and ramdisk to correct address */
+		memmove((void*) hdr->kernel_addr, (char *)(image_addr + page_size), hdr->kernel_size);
+		memmove((void*) hdr->ramdisk_addr, (char *)(image_addr + page_size + kernel_actual), hdr->ramdisk_size);
+#if DEVICE_TREE
+		/* Validate and Read device device tree in the "tags_add */
+		if (check_aboot_addr_range_overlap(hdr->tags_addr, dt_entry.size))
+		{
+			dprintf(CRITICAL, "Device tree addresses overlap with aboot addresses.\n");
+			return -1;
+		}
+
+		memmove((void*) hdr->tags_addr, (char *)(image_addr + page_size + kernel_actual + ramdisk_actual), hdr->dt_size);
+#endif
+
+		/* Make sure everything from scratch address is read before next step!*/
+		if(device.is_tampered)
+		{
+			write_device_info_flash(&device);
+		}
+#if USE_PCOM_SECBOOT
+		set_tamper_flag(device.is_tampered);
+#endif
+	}
+	else
+	{
+		offset = page_size;
+
+		kernel_actual = ROUND_TO_PAGE(hdr->kernel_size, page_mask);
+		ramdisk_actual = ROUND_TO_PAGE(hdr->ramdisk_size, page_mask);
+		second_actual = ROUND_TO_PAGE(hdr->second_size, page_mask);
+
+		dprintf(INFO, "Loading boot image (%d): start\n",
+				kernel_actual + ramdisk_actual);
+		bs_set_timestamp(BS_KERNEL_LOAD_START);
+
+		if (flash_read(ptn, offset, (void *)hdr->kernel_addr, kernel_actual)) {
+			dprintf(CRITICAL, "ERROR: Cannot read kernel image\n");
+			return -1;
+		}
+		offset += kernel_actual;
+
+		if (flash_read(ptn, offset, (void *)hdr->ramdisk_addr, ramdisk_actual)) {
+			dprintf(CRITICAL, "ERROR: Cannot read ramdisk image\n");
+			return -1;
+		}
+		offset += ramdisk_actual;
+
+		dprintf(INFO, "Loading boot image (%d): done\n",
+				kernel_actual + ramdisk_actual);
+		bs_set_timestamp(BS_KERNEL_LOAD_DONE);
+
+		if(hdr->second_size != 0) {
+			offset += second_actual;
+			/* Second image loading not implemented. */
+			ASSERT(0);
+		}
+
+#if DEVICE_TREE
+		if(hdr->dt_size != 0) {
+
+			/* Read the device tree table into buffer */
+			if(flash_read(ptn, offset, (void *) dt_buf, page_size)) {
+				dprintf(CRITICAL, "ERROR: Cannot read the Device Tree Table\n");
+				return -1;
+			}
+
+			table = (struct dt_table*) dt_buf;
+
+			if (dev_tree_validate(table, hdr->page_size, &dt_hdr_size) != 0) {
+				dprintf(CRITICAL, "ERROR: Cannot validate Device Tree Table \n");
+				return -1;
+			}
+
+			table = (struct dt_table*) memalign(CACHE_LINE, dt_hdr_size);
+			if (!table)
+				return -1;
+
+			/* Read the entire device tree table into buffer */
+			if(flash_read(ptn, offset, (void *)table, dt_hdr_size)) {
+				dprintf(CRITICAL, "ERROR: Cannot read the Device Tree Table\n");
+				return -1;
+			}
+
+
+			/* Find index of device tree within device tree table */
+			if(dev_tree_get_entry_info(table, &dt_entry) != 0){
+				dprintf(CRITICAL, "ERROR: Getting device tree address failed\n");
+				return -1;
+			}
+
+			/* Validate and Read device device tree in the "tags_add */
+			if (check_aboot_addr_range_overlap(hdr->tags_addr, dt_entry.size))
+			{
+				dprintf(CRITICAL, "Device tree addresses overlap with aboot addresses.\n");
+				return -1;
+			}
+
+			/* Read device device tree in the "tags_add */
+			if(flash_read(ptn, offset + dt_entry.offset,
+						 (void *)hdr->tags_addr, dt_entry.size)) {
+				dprintf(CRITICAL, "ERROR: Cannot read device tree\n");
+				return -1;
+			}
+		}
+#endif
+
+	}
+continue_boot:
+
+	/* TODO: create/pass atags to kernel */
+
+	boot_linux((void *)hdr->kernel_addr, (void *)hdr->tags_addr,
+		   (const char *)hdr->cmdline, board_machtype(),
+		   (void *)hdr->ramdisk_addr, hdr->ramdisk_size);
+
+	return 0;
+}
+
+BUF_DMA_ALIGN(info_buf, BOOT_IMG_MAX_PAGE_SIZE);
+void write_device_info_mmc(device_info *dev)
+{
+	struct device_info *info = (void*) info_buf;
+	unsigned long long ptn = 0;
+	unsigned long long size;
+	int index = INVALID_PTN;
+	uint32_t blocksize;
+	uint8_t lun = 0;
+
+	index = partition_get_index("aboot");
+	ptn = partition_get_offset(index);
+	if(ptn == 0)
+	{
+		return;
+	}
+
+	lun = partition_get_lun(index);
+	mmc_set_lun(lun);
+
+	size = partition_get_size(index);
+
+	memcpy(info, dev, sizeof(device_info));
+
+	blocksize = mmc_get_device_blocksize();
+
+	if(mmc_write((ptn + size - blocksize), blocksize, (void *)info_buf))
+	{
+		dprintf(CRITICAL, "ERROR: Cannot write device info\n");
+		return;
+	}
+}
+
+void read_device_info_mmc(device_info *dev)
+{
+	struct device_info *info = (void*) info_buf;
+	unsigned long long ptn = 0;
+	unsigned long long size;
+	int index = INVALID_PTN;
+	uint32_t blocksize;
+
+	index = partition_get_index("aboot");
+	ptn = partition_get_offset(index);
+	if(ptn == 0)
+	{
+		return;
+	}
+
+	size = partition_get_size(index);
+
+	blocksize = mmc_get_device_blocksize();
+
+	if(mmc_read((ptn + size - blocksize), (void *)info_buf, blocksize))
+	{
+		dprintf(CRITICAL, "ERROR: Cannot read device info\n");
+		return;
+	}
+
+	if (memcmp(info->magic, DEVICE_MAGIC, DEVICE_MAGIC_SIZE))
+	{
+		memcpy(info->magic, DEVICE_MAGIC, DEVICE_MAGIC_SIZE);
+		info->is_unlocked = 0;
+		info->is_tampered = 0;
+		info->charger_screen_enabled = 0;
+
+		write_device_info_mmc(info);
+	}
+	memcpy(dev, info, sizeof(device_info));
+}
+
+void write_device_info_flash(device_info *dev)
+{
+	struct device_info *info = (void *) info_buf;
+	struct ptentry *ptn;
+	struct ptable *ptable;
+
+	ptable = flash_get_ptable();
+	if (ptable == NULL)
+	{
+		dprintf(CRITICAL, "ERROR: Partition table not found\n");
+		return;
+	}
+
+	ptn = ptable_find(ptable, "devinfo");
+	if (ptn == NULL)
+	{
+		dprintf(CRITICAL, "ERROR: No boot partition found\n");
+			return;
+	}
+
+	memcpy(info, dev, sizeof(device_info));
+
+	if (flash_write(ptn, 0, (void *)info_buf, page_size))
+	{
+		dprintf(CRITICAL, "ERROR: Cannot write device info\n");
+			return;
+	}
+}
+
+void read_device_info_flash(device_info *dev)
+{
+	struct device_info *info = (void*) info_buf;
+	struct ptentry *ptn;
+	struct ptable *ptable;
+
+	ptable = flash_get_ptable();
+	if (ptable == NULL)
+	{
+		dprintf(CRITICAL, "ERROR: Partition table not found\n");
+		return;
+	}
+
+	ptn = ptable_find(ptable, "devinfo");
+	if (ptn == NULL)
+	{
+		dprintf(CRITICAL, "ERROR: No boot partition found\n");
+			return;
+	}
+
+	if (flash_read(ptn, 0, (void *)info_buf, page_size))
+	{
+		dprintf(CRITICAL, "ERROR: Cannot write device info\n");
+			return;
+	}
+
+	if (memcmp(info->magic, DEVICE_MAGIC, DEVICE_MAGIC_SIZE))
+	{
+		memcpy(info->magic, DEVICE_MAGIC, DEVICE_MAGIC_SIZE);
+		info->is_unlocked = 0;
+		info->is_tampered = 0;
+		write_device_info_flash(info);
+	}
+	memcpy(dev, info, sizeof(device_info));
+}
+
+void write_device_info(device_info *dev)
+{
+	if(target_is_emmc_boot())
+	{
+		write_device_info_mmc(dev);
+	}
+	else
+	{
+		write_device_info_flash(dev);
+	}
+}
+
+void read_device_info(device_info *dev)
+{
+	if(target_is_emmc_boot())
+	{
+		read_device_info_mmc(dev);
+	}
+	else
+	{
+		read_device_info_flash(dev);
+	}
+}
+
+void reset_device_info()
+{
+	dprintf(ALWAYS, "reset_device_info called.");
+	device.is_tampered = 0;
+	write_device_info(&device);
+}
+
+void set_device_root()
+{
+	dprintf(ALWAYS, "set_device_root called.");
+	device.is_tampered = 1;
+	write_device_info(&device);
+}
+
+#if DEVICE_TREE
+int copy_dtb(uint8_t *boot_image_start)
+{
+	uint32 dt_image_offset = 0;
+	uint32_t n;
+	struct dt_table *table;
+	struct dt_entry dt_entry;
+	uint32_t dt_hdr_size;
+
+	struct boot_img_hdr *hdr = (struct boot_img_hdr *) (boot_image_start);
+
+	if(hdr->dt_size != 0) {
+
+		/* add kernel offset */
+		dt_image_offset += page_size;
+		n = ROUND_TO_PAGE(hdr->kernel_size, page_mask);
+		dt_image_offset += n;
+
+		/* add ramdisk offset */
+		n = ROUND_TO_PAGE(hdr->ramdisk_size, page_mask);
+		dt_image_offset += n;
+
+		/* add second offset */
+		if(hdr->second_size != 0) {
+			n = ROUND_TO_PAGE(hdr->second_size, page_mask);
+			dt_image_offset += n;
+		}
+
+		/* offset now point to start of dt.img */
+		table = (struct dt_table*)(boot_image_start + dt_image_offset);
+
+		if (dev_tree_validate(table, hdr->page_size, &dt_hdr_size) != 0) {
+			dprintf(CRITICAL, "ERROR: Cannot validate Device Tree Table \n");
+			return -1;
+		}
+		/* Find index of device tree within device tree table */
+		if(dev_tree_get_entry_info(table, &dt_entry) != 0){
+			dprintf(CRITICAL, "ERROR: Getting device tree address failed\n");
+			return -1;
+		}
+
+		/* Validate and Read device device tree in the "tags_add */
+		if (check_aboot_addr_range_overlap(hdr->tags_addr, dt_entry.size))
+		{
+			dprintf(CRITICAL, "Device tree addresses overlap with aboot addresses.\n");
+			return -1;
+		}
+
+		/* Read device device tree in the "tags_add */
+		memmove((void*) hdr->tags_addr,
+				boot_image_start + dt_image_offset +  dt_entry.offset,
+				dt_entry.size);
+	} else
+		return -1;
+
+	/* Everything looks fine. Return success. */
+	return 0;
+}
+#endif
+
+void cmd_boot(const char *arg, void *data, unsigned sz)
+{
+	unsigned kernel_actual;
+	unsigned ramdisk_actual;
+	uint32_t image_actual;
+	uint32_t dt_actual = 0;
+	uint32_t sig_actual = SIGNATURE_SIZE;
+	struct boot_img_hdr *hdr;
+	struct kernel64_hdr *kptr;
+	char *ptr = ((char*) data);
+	int ret = 0;
+	uint8_t dtb_copied = 0;
+
+	if (sz < sizeof(hdr)) {
+		fastboot_fail("invalid bootimage header");
+		return;
+	}
+
+	hdr = (struct boot_img_hdr *)data;
+
+	/* ensure commandline is terminated */
+	hdr->cmdline[BOOT_ARGS_SIZE-1] = 0;
+
+	if(target_is_emmc_boot() && hdr->page_size) {
+		page_size = hdr->page_size;
+		page_mask = page_size - 1;
+	}
+
+	kernel_actual = ROUND_TO_PAGE(hdr->kernel_size, page_mask);
+	ramdisk_actual = ROUND_TO_PAGE(hdr->ramdisk_size, page_mask);
+#if DEVICE_TREE
+	dt_actual = ROUND_TO_PAGE(hdr->dt_size, page_mask);
+#endif
+
+	image_actual = ADD_OF(page_size, kernel_actual);
+	image_actual = ADD_OF(image_actual, ramdisk_actual);
+	image_actual = ADD_OF(image_actual, dt_actual);
+
+	if (target_use_signed_kernel() && (!device.is_unlocked))
+		image_actual = ADD_OF(image_actual, sig_actual);
+
+	/* sz should have atleast raw boot image */
+	if (image_actual > sz) {
+		fastboot_fail("bootimage: incomplete or not signed");
+		return;
+	}
+
+	/* Verify the boot image
+	 * device & page_size are initialized in aboot_init
+	 */
+	if (target_use_signed_kernel() && (!device.is_unlocked))
+		/* Pass size excluding signature size, otherwise we would try to
+		 * access signature beyond its length
+		 */
+		verify_signed_bootimg((uint32_t)data, (image_actual - sig_actual));
+
+	/*
+	 * Update the kernel/ramdisk/tags address if the boot image header
+	 * has default values, these default values come from mkbootimg when
+	 * the boot image is flashed using fastboot flash:raw
+	 */
+	kptr = (struct kernel64_hdr*)((char*) data + page_size);
+	update_ker_tags_rdisk_addr(hdr, IS_ARM64(kptr));
+
+	/* Get virtual addresses since the hdr saves physical addresses. */
+	hdr->kernel_addr = VA(hdr->kernel_addr);
+	hdr->ramdisk_addr = VA(hdr->ramdisk_addr);
+	hdr->tags_addr = VA(hdr->tags_addr);
+
+	/* Check if the addresses in the header are valid. */
+	if (check_aboot_addr_range_overlap(hdr->kernel_addr, kernel_actual) ||
+		check_aboot_addr_range_overlap(hdr->ramdisk_addr, ramdisk_actual))
+	{
+		dprintf(CRITICAL, "kernel/ramdisk addresses overlap with aboot addresses.\n");
+		return;
+	}
+
+#if DEVICE_TREE
+	/* find correct dtb and copy it to right location */
+	ret = copy_dtb(data);
+
+	dtb_copied = !ret ? 1 : 0;
+#else
+	if (check_aboot_addr_range_overlap(hdr->tags_addr, MAX_TAGS_SIZE))
+	{
+		dprintf(CRITICAL, "Tags addresses overlap with aboot addresses.\n");
+		return;
+	}
+#endif
+
+	/* Load ramdisk & kernel */
+	memmove((void*) hdr->ramdisk_addr, ptr + page_size + kernel_actual, hdr->ramdisk_size);
+	memmove((void*) hdr->kernel_addr, ptr + page_size, hdr->kernel_size);
+
+#if DEVICE_TREE
+	/*
+	 * If dtb is not found look for appended DTB in the kernel.
+	 * If appended dev tree is found, update the atags with
+	 * memory address to the DTB appended location on RAM.
+	 * Else update with the atags address in the kernel header
+	 */
+	if (!dtb_copied) {
+		void *dtb;
+		dtb = dev_tree_appended((void *)hdr->kernel_addr, hdr->kernel_size,
+					(void *)hdr->tags_addr);
+		if (!dtb) {
+			fastboot_fail("dtb not found");
+			return;
+		}
+	}
+#endif
+
+#ifndef DEVICE_TREE
+	if (check_aboot_addr_range_overlap(hdr->tags_addr, MAX_TAGS_SIZE))
+	{
+		dprintf(CRITICAL, "Tags addresses overlap with aboot addresses.\n");
+		return;
+	}
+#endif
+
+	fastboot_okay("");
+	fastboot_stop();
+
+	boot_linux((void*) hdr->kernel_addr, (void*) hdr->tags_addr,
+		   (const char*) hdr->cmdline, board_machtype(),
+		   (void*) hdr->ramdisk_addr, hdr->ramdisk_size);
+}
+
+void cmd_erase(const char *arg, void *data, unsigned sz)
+{
+	struct ptentry *ptn;
+	struct ptable *ptable;
+
+	ptable = flash_get_ptable();
+	if (ptable == NULL) {
+		fastboot_fail("partition table doesn't exist");
+		return;
+	}
+
+	ptn = ptable_find(ptable, arg);
+	if (ptn == NULL) {
+		fastboot_fail("unknown partition name");
+		return;
+	}
+
+	if (flash_erase(ptn)) {
+		fastboot_fail("failed to erase partition");
+		return;
+	}
+	fastboot_okay("");
+}
+
+
+void cmd_erase_mmc(const char *arg, void *data, unsigned sz)
+{
+	BUF_DMA_ALIGN(out, DEFAULT_ERASE_SIZE);
+	unsigned long long ptn = 0;
+	unsigned long long size = 0;
+	int index = INVALID_PTN;
+	uint8_t lun = 0;
+
+	index = partition_get_index(arg);
+	ptn = partition_get_offset(index);
+	size = partition_get_size(index);
+
+	if(ptn == 0) {
+		fastboot_fail("Partition table doesn't exist\n");
+		return;
+	}
+
+	lun = partition_get_lun(index);
+	mmc_set_lun(lun);
+
+#if MMC_SDHCI_SUPPORT
+	if (mmc_erase_card(ptn, size)) {
+		fastboot_fail("failed to erase partition\n");
+		return;
+	}
+#else
+	size = partition_get_size(index);
+	if (size > DEFAULT_ERASE_SIZE)
+		size = DEFAULT_ERASE_SIZE;
+
+	/* Simple inefficient version of erase. Just writing
+       0 in first several blocks */
+	if (mmc_write(ptn , size, (unsigned int *)out)) {
+		fastboot_fail("failed to erase partition");
+		return;
+	}
+#endif
+	fastboot_okay("");
+}
+
+
+void cmd_flash_mmc_img(const char *arg, void *data, unsigned sz)
+{
+	unsigned long long ptn = 0;
+	unsigned long long size = 0;
+	int index = INVALID_PTN;
+	char *token = NULL;
+	char *pname = NULL;
+	uint8_t lun = 0;
+	bool lun_set = false;
+
+	token = strtok(arg, ":");
+	pname = token;
+	token = strtok(NULL, ":");
+	if(token)
+	{
+		lun = atoi(token);
+		mmc_set_lun(lun);
+		lun_set = true;
+	}
+
+	if (pname)
+	{
+		if (!strcmp(pname, "partition"))
+		{
+			dprintf(INFO, "Attempt to write partition image.\n");
+			if (write_partition(sz, (unsigned char *) data)) {
+				fastboot_fail("failed to write partition");
+				return;
+			}
+		}
+		else
+		{
+			index = partition_get_index(pname);
+			ptn = partition_get_offset(index);
+			if(ptn == 0) {
+				fastboot_fail("partition table doesn't exist");
+				return;
+			}
+
+			if (!strcmp(pname, "boot") || !strcmp(pname, "recovery")) {
+				if (memcmp((void *)data, BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
+					fastboot_fail("image is not a boot image");
+					return;
+				}
+			}
+
+			if(!lun_set)
+			{
+				lun = partition_get_lun(index);
+				mmc_set_lun(lun);
+			}
+
+			size = partition_get_size(index);
+			if (ROUND_TO_PAGE(sz,511) > size) {
+				fastboot_fail("size too large");
+				return;
+			}
+			else if (mmc_write(ptn , sz, (unsigned int *)data)) {
+				fastboot_fail("flash write failure");
+				return;
+			}
+		}
+	}
+	fastboot_okay("");
+	return;
+}
+
+void cmd_flash_mmc_sparse_img(const char *arg, void *data, unsigned sz)
+{
+	unsigned int chunk;
+	unsigned int chunk_data_sz;
+	uint32_t *fill_buf = NULL;
+	uint32_t fill_val;
+	uint32_t chunk_blk_cnt = 0;
+	sparse_header_t *sparse_header;
+	chunk_header_t *chunk_header;
+	uint32_t total_blocks = 0;
+	unsigned long long ptn = 0;
+	unsigned long long size = 0;
+	int index = INVALID_PTN;
+	int i;
+	uint8_t lun = 0;
+
+	index = partition_get_index(arg);
+	ptn = partition_get_offset(index);
+	if(ptn == 0) {
+		fastboot_fail("partition table doesn't exist");
+		return;
+	}
+
+	size = partition_get_size(index);
+	if (ROUND_TO_PAGE(sz,511) > size) {
+		fastboot_fail("size too large");
+		return;
+	}
+
+	lun = partition_get_lun(index);
+	mmc_set_lun(lun);
+
+	/* Read and skip over sparse image header */
+	sparse_header = (sparse_header_t *) data;
+	if ((sparse_header->total_blks * sparse_header->blk_sz) > size) {
+		fastboot_fail("size too large");
+		return;
+	}
+
+	data += sparse_header->file_hdr_sz;
+	if(sparse_header->file_hdr_sz > sizeof(sparse_header_t))
+	{
+		/* Skip the remaining bytes in a header that is longer than
+		 * we expected.
+		 */
+		data += (sparse_header->file_hdr_sz - sizeof(sparse_header_t));
+	}
+
+	dprintf (SPEW, "=== Sparse Image Header ===\n");
+	dprintf (SPEW, "magic: 0x%x\n", sparse_header->magic);
+	dprintf (SPEW, "major_version: 0x%x\n", sparse_header->major_version);
+	dprintf (SPEW, "minor_version: 0x%x\n", sparse_header->minor_version);
+	dprintf (SPEW, "file_hdr_sz: %d\n", sparse_header->file_hdr_sz);
+	dprintf (SPEW, "chunk_hdr_sz: %d\n", sparse_header->chunk_hdr_sz);
+	dprintf (SPEW, "blk_sz: %d\n", sparse_header->blk_sz);
+	dprintf (SPEW, "total_blks: %d\n", sparse_header->total_blks);
+	dprintf (SPEW, "total_chunks: %d\n", sparse_header->total_chunks);
+
+	/* Start processing chunks */
+	for (chunk=0; chunk<sparse_header->total_chunks; chunk++)
+	{
+		/* Read and skip over chunk header */
+		chunk_header = (chunk_header_t *) data;
+		data += sizeof(chunk_header_t);
+
+		dprintf (SPEW, "=== Chunk Header ===\n");
+		dprintf (SPEW, "chunk_type: 0x%x\n", chunk_header->chunk_type);
+		dprintf (SPEW, "chunk_data_sz: 0x%x\n", chunk_header->chunk_sz);
+		dprintf (SPEW, "total_size: 0x%x\n", chunk_header->total_sz);
+
+		if(sparse_header->chunk_hdr_sz > sizeof(chunk_header_t))
+		{
+			/* Skip the remaining bytes in a header that is longer than
+			 * we expected.
+			 */
+			data += (sparse_header->chunk_hdr_sz - sizeof(chunk_header_t));
+		}
+
+		chunk_data_sz = sparse_header->blk_sz * chunk_header->chunk_sz;
+		switch (chunk_header->chunk_type)
+		{
+			case CHUNK_TYPE_RAW:
+			if(chunk_header->total_sz != (sparse_header->chunk_hdr_sz +
+											chunk_data_sz))
+			{
+				fastboot_fail("Bogus chunk size for chunk type Raw");
+				return;
+			}
+
+			if(mmc_write(ptn + ((uint64_t)total_blocks*sparse_header->blk_sz),
+						chunk_data_sz,
+						(unsigned int*)data))
+			{
+				fastboot_fail("flash write failure");
+				return;
+			}
+			total_blocks += chunk_header->chunk_sz;
+			data += chunk_data_sz;
+			break;
+
+			case CHUNK_TYPE_FILL:
+			if(chunk_header->total_sz != (sparse_header->chunk_hdr_sz +
+											sizeof(uint32_t)))
+			{
+				fastboot_fail("Bogus chunk size for chunk type FILL");
+				return;
+			}
+
+			fill_buf = (uint32_t *)memalign(CACHE_LINE, ROUNDUP(sparse_header->blk_sz, CACHE_LINE));
+			if (!fill_buf)
+			{
+				fastboot_fail("Malloc failed for: CHUNK_TYPE_FILL");
+				return;
+			}
+
+			fill_val = *(uint32_t *)data;
+			data = (char *) data + sizeof(uint32_t);
+			chunk_blk_cnt = chunk_data_sz / sparse_header->blk_sz;
+
+			for (i = 0; i < (sparse_header->blk_sz / sizeof(fill_val)); i++)
+			{
+				fill_buf[i] = fill_val;
+			}
+
+			for (i = 0; i < chunk_blk_cnt; i++)
+			{
+				if(mmc_write(ptn + ((uint64_t)total_blocks*sparse_header->blk_sz),
+							sparse_header->blk_sz,
+							fill_buf))
+				{
+					fastboot_fail("flash write failure");
+					free(fill_buf);
+					return;
+				}
+
+				total_blocks++;
+			}
+
+			free(fill_buf);
+			break;
+
+			case CHUNK_TYPE_DONT_CARE:
+			total_blocks += chunk_header->chunk_sz;
+			break;
+
+			case CHUNK_TYPE_CRC:
+			if(chunk_header->total_sz != sparse_header->chunk_hdr_sz)
+			{
+				fastboot_fail("Bogus chunk size for chunk type Dont Care");
+				return;
+			}
+			total_blocks += chunk_header->chunk_sz;
+			data += chunk_data_sz;
+			break;
+
+			default:
+			dprintf(CRITICAL, "Unkown chunk type: %x\n",chunk_header->chunk_type);
+			fastboot_fail("Unknown chunk type");
+			return;
+		}
+	}
+
+	dprintf(INFO, "Wrote %d blocks, expected to write %d blocks\n",
+					total_blocks, sparse_header->total_blks);
+
+	if(total_blocks != sparse_header->total_blks)
+	{
+		fastboot_fail("sparse image write failure");
+	}
+
+	fastboot_okay("");
+	return;
+}
+
+void cmd_flash_mmc(const char *arg, void *data, unsigned sz)
+{
+	sparse_header_t *sparse_header;
+	/* 8 Byte Magic + 2048 Byte xml + Encrypted Data */
+	unsigned int *magic_number = (unsigned int *) data;
+
+#ifdef SSD_ENABLE
+	int              ret=0;
+	uint32           major_version=0;
+	uint32           minor_version=0;
+
+	ret = scm_svc_version(&major_version,&minor_version);
+	if(!ret)
+	{
+		if(major_version >= 2)
+		{
+			if( !strcmp(arg, "ssd") || !strcmp(arg, "tqs") )
+			{
+				ret = encrypt_scm((uint32 **) &data, &sz);
+				if (ret != 0) {
+					dprintf(CRITICAL, "ERROR: Encryption Failure\n");
+					return;
+				}
+
+				/* Protect only for SSD */
+				if (!strcmp(arg, "ssd")) {
+					ret = scm_protect_keystore((uint32 *) data, sz);
+					if (ret != 0) {
+						dprintf(CRITICAL, "ERROR: scm_protect_keystore Failed\n");
+						return;
+					}
+				}
+			}
+			else
+			{
+				ret = decrypt_scm_v2((uint32 **) &data, &sz);
+				if(ret != 0)
+				{
+					dprintf(CRITICAL,"ERROR: Decryption Failure\n");
+					return;
+				}
+			}
+		}
+		else
+		{
+			if (magic_number[0] == DECRYPT_MAGIC_0 &&
+			magic_number[1] == DECRYPT_MAGIC_1)
+			{
+				ret = decrypt_scm((uint32 **) &data, &sz);
+				if (ret != 0) {
+					dprintf(CRITICAL, "ERROR: Invalid secure image\n");
+					return;
+				}
+			}
+			else if (magic_number[0] == ENCRYPT_MAGIC_0 &&
+				magic_number[1] == ENCRYPT_MAGIC_1)
+			{
+				ret = encrypt_scm((uint32 **) &data, &sz);
+				if (ret != 0) {
+					dprintf(CRITICAL, "ERROR: Encryption Failure\n");
+					return;
+				}
+			}
+		}
+	}
+	else
+	{
+		dprintf(CRITICAL,"INVALID SVC Version\n");
+		return;
+	}
+#endif /* SSD_ENABLE */
+
+	sparse_header = (sparse_header_t *) data;
+	if (sparse_header->magic != SPARSE_HEADER_MAGIC)
+		cmd_flash_mmc_img(arg, data, sz);
+	else
+		cmd_flash_mmc_sparse_img(arg, data, sz);
+	return;
+}
+
+void cmd_flash(const char *arg, void *data, unsigned sz)
+{
+	struct ptentry *ptn;
+	struct ptable *ptable;
+	unsigned extra = 0;
+
+	ptable = flash_get_ptable();
+	if (ptable == NULL) {
+		fastboot_fail("partition table doesn't exist");
+		return;
+	}
+
+	ptn = ptable_find(ptable, arg);
+	if (ptn == NULL) {
+		fastboot_fail("unknown partition name");
+		return;
+	}
+
+	if (!strcmp(ptn->name, "boot") || !strcmp(ptn->name, "recovery")) {
+		if (memcmp((void *)data, BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
+			fastboot_fail("image is not a boot image");
+			return;
+		}
+	}
+
+	if (!strcmp(ptn->name, "system")
+		|| !strcmp(ptn->name, "userdata")
+		|| !strcmp(ptn->name, "persist")
+		|| !strcmp(ptn->name, "recoveryfs")
+		|| !strcmp(ptn->name, "modem"))
+	{
+		if (memcmp((void *)data, UBI_MAGIC, UBI_MAGIC_SIZE))
+			extra = 1;
+		else
+			extra = 0;
+	}
+	else
+		sz = ROUND_TO_PAGE(sz, page_mask);
+
+	dprintf(INFO, "writing %d bytes to '%s'\n", sz, ptn->name);
+	if (flash_write(ptn, extra, data, sz)) {
+		fastboot_fail("flash write failure");
+		return;
+	}
+	dprintf(INFO, "partition '%s' updated\n", ptn->name);
+	fastboot_okay("");
+}
+
+void cmd_continue(const char *arg, void *data, unsigned sz)
+{
+	fastboot_okay("");
+	fastboot_stop();
+	if (target_is_emmc_boot())
+	{
+		boot_linux_from_mmc();
+	}
+	else
+	{
+		boot_linux_from_flash();
+	}
+}
+
+void cmd_reboot(const char *arg, void *data, unsigned sz)
+{
+	dprintf(INFO, "rebooting the device\n");
+	fastboot_okay("");
+	reboot_device(0);
+}
+
+void cmd_reboot_bootloader(const char *arg, void *data, unsigned sz)
+{
+	dprintf(INFO, "rebooting the device\n");
+	fastboot_okay("");
+	reboot_device(FASTBOOT_MODE);
+}
+
+void cmd_oem_enable_charger_screen(const char *arg, void *data, unsigned size)
+{
+	dprintf(INFO, "Enabling charger screen check\n");
+	device.charger_screen_enabled = 1;
+	write_device_info(&device);
+	fastboot_okay("");
+}
+
+void cmd_oem_disable_charger_screen(const char *arg, void *data, unsigned size)
+{
+	dprintf(INFO, "Disabling charger screen check\n");
+	device.charger_screen_enabled = 0;
+	write_device_info(&device);
+	fastboot_okay("");
+}
+
+void cmd_oem_select_display_panel(const char *arg, void *data, unsigned size)
+{
+	dprintf(INFO, "Selecting display panel %s\n", arg);
+	if (arg)
+		strlcpy(device.display_panel, arg,
+			sizeof(device.display_panel));
+	write_device_info(&device);
+	fastboot_okay("");
+}
+
+void cmd_oem_unlock(const char *arg, void *data, unsigned sz)
+{
+	if(!device.is_unlocked)
+	{
+		device.is_unlocked = 1;
+		write_device_info(&device);
+	}
+	fastboot_okay("");
+}
+
+void cmd_oem_devinfo(const char *arg, void *data, unsigned sz)
+{
+	char response[128];
+	snprintf(response, sizeof(response), "\tDevice tampered: %s", (device.is_tampered ? "true" : "false"));
+	fastboot_info(response);
+	snprintf(response, sizeof(response), "\tDevice unlocked: %s", (device.is_unlocked ? "true" : "false"));
+	fastboot_info(response);
+	snprintf(response, sizeof(response), "\tCharger screen enabled: %s", (device.charger_screen_enabled ? "true" : "false"));
+	fastboot_info(response);
+	snprintf(response, sizeof(response), "\tDisplay panel: %s", (device.display_panel));
+	fastboot_info(response);
+	fastboot_okay("");
+}
+
+void cmd_preflash(const char *arg, void *data, unsigned sz)
+{
+	fastboot_okay("");
+}
+
+static struct fbimage logo_header = {0};
+struct fbimage* splash_screen_flash();
+
+int splash_screen_check_header(struct fbimage *logo)
+{
+	if (memcmp(logo->header.magic, LOGO_IMG_MAGIC, 8))
+		return -1;
+	if (logo->header.width == 0 || logo->header.height == 0)
+		return -1;
+	return 0;
+}
+
+struct fbimage* splash_screen_flash()
+{
+	struct ptentry *ptn;
+	struct ptable *ptable;
+	struct fbcon_config *fb_display = NULL;
+	struct fbimage *logo = &logo_header;
+
+
+	ptable = flash_get_ptable();
+	if (ptable == NULL) {
+	dprintf(CRITICAL, "ERROR: Partition table not found\n");
+	return NULL;
+	}
+	ptn = ptable_find(ptable, "splash");
+	if (ptn == NULL) {
+		dprintf(CRITICAL, "ERROR: splash Partition not found\n");
+		return NULL;
+	}
+
+	if (flash_read(ptn, 0,(unsigned int *) logo, sizeof(logo->header))) {
+		dprintf(CRITICAL, "ERROR: Cannot read boot image header\n");
+		return NULL;
+	}
+
+	if (splash_screen_check_header(logo)) {
+		dprintf(CRITICAL, "ERROR: Boot image header invalid\n");
+		return NULL;
+	}
+
+	fb_display = fbcon_display();
+	if (fb_display) {
+		uint8_t *base = (uint8_t *) fb_display->base;
+		if (logo->header.width != fb_display->width || logo->header.height != fb_display->height) {
+				base += LOGO_IMG_OFFSET;
+		}
+
+		if (flash_read(ptn + sizeof(logo->header), 0,
+			base,
+			((((logo->header.width * logo->header.height * fb_display->bpp/8) + 511) >> 9) << 9))) {
+			fbcon_clear();
+			dprintf(CRITICAL, "ERROR: Cannot read splash image\n");
+			return NULL;
+		}
+		logo->image = base;
+	}
+
+	return logo;
+}
+
+struct fbimage* splash_screen_mmc()
+{
+	int index = INVALID_PTN;
+	unsigned long long ptn = 0;
+	struct fbcon_config *fb_display = NULL;
+	struct fbimage *logo = &logo_header;
+
+	index = partition_get_index("splash");
+	if (index == 0) {
+		dprintf(CRITICAL, "ERROR: splash Partition table not found\n");
+		return NULL;
+	}
+
+	ptn = partition_get_offset(index);
+	if (ptn == 0) {
+		dprintf(CRITICAL, "ERROR: splash Partition invalid\n");
+		return NULL;
+	}
+
+	if (mmc_read(ptn, (unsigned int *) logo, sizeof(logo->header))) {
+		dprintf(CRITICAL, "ERROR: Cannot read splash image header\n");
+		return NULL;
+	}
+
+	if (splash_screen_check_header(logo)) {
+		dprintf(CRITICAL, "ERROR: Splash image header invalid\n");
+		return NULL;
+	}
+
+	fb_display = fbcon_display();
+	if (fb_display) {
+		uint8_t *base = (uint8_t *) fb_display->base;
+		if (logo->header.width != fb_display->width || logo->header.height != fb_display->height)
+				base += LOGO_IMG_OFFSET;
+
+		if (mmc_read(ptn + sizeof(logo->header),
+			base,
+			((((logo->header.width * logo->header.height * fb_display->bpp/8) + 511) >> 9) << 9))) {
+			fbcon_clear();
+			dprintf(CRITICAL, "ERROR: Cannot read splash image\n");
+			return NULL;
+		}
+
+		logo->image = base;
+	}
+
+	return logo;
+}
+
+
+struct fbimage* fetch_image_from_partition()
+{
+	if (target_is_emmc_boot()) {
+		return splash_screen_mmc();
+	} else {
+		return splash_screen_flash();
+	}
+}
+
+/* Get the size from partiton name */
+static void get_partition_size(const char *arg, char *response)
+{
+	uint64_t ptn = 0;
+	uint64_t size;
+	int index = INVALID_PTN;
+
+	index = partition_get_index(arg);
+
+	if (index == INVALID_PTN)
+	{
+		dprintf(CRITICAL, "Invalid partition index\n");
+		return;
+	}
+
+	ptn = partition_get_offset(index);
+
+	if(!ptn)
+	{
+		dprintf(CRITICAL, "Invalid partition name %s\n", arg);
+		return;
+	}
+
+	size = partition_get_size(index);
+
+	snprintf(response, MAX_RSP_SIZE, "\t 0x%llx", size);
+	return;
+}
+
+/*
+ * Publish the partition type & size info
+ * fastboot getvar will publish the required information.
+ * fastboot getvar partition_size:<partition_name>: partition size in hex
+ * fastboot getvar partition_type:<partition_name>: partition type (ext/fat)
+ */
+static void publish_getvar_partition_info(struct getvar_partition_info *info, uint8_t num_parts)
+{
+	uint8_t i;
+
+	for (i = 0; i < num_parts; i++) {
+		get_partition_size(info[i].part_name, info[i].size_response);
+
+		if (strlcat(info[i].getvar_size, info[i].part_name, MAX_GET_VAR_NAME_SIZE) >= MAX_GET_VAR_NAME_SIZE)
+		{
+			dprintf(CRITICAL, "partition size name truncated\n");
+			return;
+		}
+		if (strlcat(info[i].getvar_type, info[i].part_name, MAX_GET_VAR_NAME_SIZE) >= MAX_GET_VAR_NAME_SIZE)
+		{
+			dprintf(CRITICAL, "partition type name truncated\n");
+			return;
+		}
+
+		/* publish partition size & type info */
+		fastboot_publish((const char *) info[i].getvar_size, (const char *) info[i].size_response);
+		fastboot_publish((const char *) info[i].getvar_type, (const char *) info[i].type_response);
+	}
+}
+
+/* register commands and variables for fastboot */
+void aboot_fastboot_register_commands(void)
+{
+	if (target_is_emmc_boot())
+	{
+		fastboot_register("flash:", cmd_flash_mmc);
+		fastboot_register("erase:", cmd_erase_mmc);
+	}
+	else
+	{
+		fastboot_register("flash:", cmd_flash);
+		fastboot_register("erase:", cmd_erase);
+	}
+
+	fastboot_register("boot",              cmd_boot);
+	fastboot_register("continue",          cmd_continue);
+	fastboot_register("reboot",            cmd_reboot);
+	fastboot_register("reboot-bootloader", cmd_reboot_bootloader);
+	fastboot_register("oem unlock",        cmd_oem_unlock);
+	fastboot_register("oem device-info",   cmd_oem_devinfo);
+	fastboot_register("preflash",          cmd_preflash);
+	fastboot_register("oem enable-charger-screen",
+			cmd_oem_enable_charger_screen);
+	fastboot_register("oem disable-charger-screen",
+			cmd_oem_disable_charger_screen);
+	fastboot_register("oem select-display-panel",
+			cmd_oem_select_display_panel);
+	/* publish variables and their values */
+	fastboot_publish("product",  TARGET(BOARD));
+	fastboot_publish("kernel",   "lk");
+	fastboot_publish("serialno", sn_buf);
+
+	/*
+	 * partition info is supported only for emmc partitions
+	 * Calling this for NAND prints some error messages which
+	 * is harmless but misleading. Avoid calling this for NAND
+	 * devices.
+	 */
+	if (target_is_emmc_boot())
+		publish_getvar_partition_info(part_info, ARRAY_SIZE(part_info));
+
+	/* Max download size supported */
+	snprintf(max_download_size, MAX_RSP_SIZE, "\t0x%x",
+			target_get_max_flash_size());
+	fastboot_publish("max-download-size", (const char *) max_download_size);
+	/* Is the charger screen check enabled */
+	snprintf(charger_screen_enabled, MAX_RSP_SIZE, "%d",
+			device.charger_screen_enabled);
+	fastboot_publish("charger-screen-enabled",
+			(const char *) charger_screen_enabled);
+	snprintf(panel_display_mode, MAX_RSP_SIZE, "%s",
+			device.display_panel);
+	fastboot_publish("display-panel",
+			(const char *) panel_display_mode);
+}
+
+void aboot_init(const struct app_descriptor *app)
+{
+	unsigned reboot_mode = 0;
+	bool boot_into_fastboot = false;
+
+	/* Setup page size information for nv storage */
+	if (target_is_emmc_boot())
+	{
+		page_size = mmc_page_size();
+		page_mask = page_size - 1;
+	}
+	else
+	{
+		page_size = flash_page_size();
+		page_mask = page_size - 1;
+	}
+
+	ASSERT((MEMBASE + MEMSIZE) > MEMBASE);
+
+	read_device_info(&device);
+
+	/* Display splash screen if enabled */
+#if DISPLAY_SPLASH_SCREEN
+	dprintf(SPEW, "Display Init: Start\n");
+	target_display_init(device.display_panel);
+	dprintf(SPEW, "Display Init: Done\n");
+#endif
+
+
+	target_serialno((unsigned char *) sn_buf);
+	dprintf(SPEW,"serial number: %s\n",sn_buf);
+
+	memset(display_panel_buf, '\0', MAX_PANEL_BUF_SIZE);
+
+	/* Check if we should do something other than booting up */
+	if (keys_get_state(KEY_VOLUMEUP) && keys_get_state(KEY_VOLUMEDOWN))
+	{
+		dprintf(ALWAYS,"dload mode key sequence detected\n");
+		if (set_download_mode(EMERGENCY_DLOAD))
+		{
+			dprintf(CRITICAL,"dload mode not supported by target\n");
+		}
+		else
+		{
+			reboot_device(DLOAD);
+			dprintf(CRITICAL,"Failed to reboot into dload mode\n");
+		}
+		boot_into_fastboot = true;
+	}
+	if (!boot_into_fastboot)
+	{
+		if (keys_get_state(KEY_HOME) || keys_get_state(KEY_VOLUMEUP))
+			boot_into_recovery = 1;
+		if (!boot_into_recovery &&
+			(keys_get_state(KEY_BACK) || keys_get_state(KEY_VOLUMEDOWN)))
+			boot_into_fastboot = true;
+	}
+	#if NO_KEYPAD_DRIVER
+	if (fastboot_trigger())
+		boot_into_fastboot = true;
+	#endif
+
+	reboot_mode = check_reboot_mode();
+	if (reboot_mode == RECOVERY_MODE) {
+		boot_into_recovery = 1;
+	} else if(reboot_mode == FASTBOOT_MODE) {
+		boot_into_fastboot = true;
+	}
+
+	if (!boot_into_fastboot)
+	{
+		if (target_is_emmc_boot())
+		{
+			if(emmc_recovery_init())
+				dprintf(ALWAYS,"error in emmc_recovery_init\n");
+			if(target_use_signed_kernel())
+			{
+				if((device.is_unlocked) || (device.is_tampered))
+				{
+				#ifdef TZ_TAMPER_FUSE
+					set_tamper_fuse_cmd();
+				#endif
+				#if USE_PCOM_SECBOOT
+					set_tamper_flag(device.is_tampered);
+				#endif
+				}
+			}
+			boot_linux_from_mmc();
+		}
+		else
+		{
+			recovery_init();
+	#if USE_PCOM_SECBOOT
+		if((device.is_unlocked) || (device.is_tampered))
+			set_tamper_flag(device.is_tampered);
+	#endif
+			boot_linux_from_flash();
+		}
+		dprintf(CRITICAL, "ERROR: Could not do normal boot. Reverting "
+			"to fastboot mode.\n");
+	}
+
+	/* We are here means regular boot did not happen. Start fastboot. */
+
+	/* register aboot specific fastboot commands */
+	aboot_fastboot_register_commands();
+
+	/* dump partition table for debug info */
+	partition_dump();
+
+	/* initialize and start fastboot */
+	fastboot_init(target_get_scratch_address(), target_get_max_flash_size());
+}
+
+uint32_t get_page_size()
+{
+	return page_size;
+}
+
+/*
+ * Calculated and save hash (SHA256) for non-signed boot image.
+ *
+ * Hash the same data that is checked on the signed boot image.
+ * Kernel and Ramdisk are already read to memory buffers.
+ * Need to read the entire device-tree from mmc
+ * since non-signed image only read the DT tags of the relevant platform.
+ *
+ * @param kernel_addr - kernel bufer
+ * @param kernel_actual - kernel size in bytes
+ * @param ramdisk_addr - ramdisk buffer
+ * @param ramdisk_actual - ramdisk size
+ * @param ptn - partition
+ * @param dt_offset - device tree offset on mmc partition
+ * @param dt_size
+ *
+ * @return int - 0 on success, negative value on failure.
+ */
+int aboot_save_boot_hash_mmc(void *kernel_addr, unsigned kernel_actual,
+		   void *ramdisk_addr, unsigned ramdisk_actual,
+		   unsigned long long ptn,
+		   unsigned dt_offset, unsigned dt_size)
+{
+	SHA256_CTX sha256_ctx;
+	char digest[32]={0};
+	char *buf = (char *)target_get_scratch_address();
+	unsigned dt_actual = ROUND_TO_PAGE(dt_size, page_mask);
+	unsigned imagesize_actual = page_size + kernel_actual + ramdisk_actual + dt_actual;
+
+	SHA256_Init(&sha256_ctx);
+
+	/* Read Boot Header */
+	if (mmc_read(ptn, buf, page_size))
+	{
+		dprintf(CRITICAL, "ERROR: mmc_read() fail.\n");
+		return -1;
+	}
+	/* Read entire Device Tree */
+	if (mmc_read(ptn + dt_offset, buf+page_size, dt_actual))
+	{
+		dprintf(CRITICAL, "ERROR: mmc_read() fail.\n");
+		return -1;
+	}
+	SHA256_Update(&sha256_ctx, buf, page_size); // Boot Header
+	SHA256_Update(&sha256_ctx, kernel_addr, kernel_actual);
+	SHA256_Update(&sha256_ctx, ramdisk_addr, ramdisk_actual);
+	SHA256_Update(&sha256_ctx, buf+page_size, dt_actual); // Device Tree
+
+	SHA256_Final(digest, &sha256_ctx);
+
+	save_kernel_hash_cmd(digest);
+	dprintf(INFO, "aboot_save_boot_hash_mmc: imagesize_actual size %d bytes.\n", (int) imagesize_actual);
+
+	return 0;
+}
+
+APP_START(aboot)
+	.init = aboot_init,
+APP_END