From 3ea0953d36023d7e50fb00b2e258d8fb2828aeac Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 3 Sep 2014 17:36:59 -0600 Subject: dm: Move pre-reloc init earlier to cope with board_early_init_f() In order to support GPIO access in board_early_init_f() we must set up driver model before this function is called. In any case, earlier is better since driver model is (or will become) a key function for most init. Signed-off-by: Simon Glass --- common/board_f.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'common') diff --git a/common/board_f.c b/common/board_f.c index 4ece2b6c9fe..ea33eadc16e 100644 --- a/common/board_f.c +++ b/common/board_f.c @@ -831,6 +831,8 @@ static init_fnc_t init_sequence_f[] = { #ifdef CONFIG_OF_CONTROL fdtdec_check_fdt, #endif + initf_malloc, + initf_dm, #if defined(CONFIG_BOARD_EARLY_INIT_F) board_early_init_f, #endif @@ -866,8 +868,6 @@ static init_fnc_t init_sequence_f[] = { sdram_adjust_866, init_timebase, #endif - initf_malloc, - initf_dm, init_baud_rate, /* initialze baudrate settings */ serial_init, /* serial communications setup */ console_init_f, /* stage 1 init of console */ -- cgit v1.3.1 From 294b91a5817147d4b7f47be2ac69bac2a1f26491 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 3 Sep 2014 17:37:00 -0600 Subject: Set up stdio earlier when using driver model Since driver model registers itself with the stdio subsystem, and we want to avoid delayed registration and other complexity associated with the current serial console, move the stdio subsystem init earlier when driver model is used for serial. This simplifies the implementation. Should there be any problems with this approach they can be dealt with as boards are converted over to use driver model for serial. Signed-off-by: Simon Glass --- common/board_r.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) (limited to 'common') diff --git a/common/board_r.c b/common/board_r.c index f9647e13583..64beae5f348 100644 --- a/common/board_r.c +++ b/common/board_r.c @@ -727,6 +727,15 @@ init_fnc_t init_sequence_r[] = { set_cpu_clk_info, /* Setup clock information */ #endif initr_reloc_global_data, + initr_barrier, + initr_malloc, + bootstage_relocate, +#ifdef CONFIG_DM_SERIAL + stdio_init, +#endif +#ifdef CONFIG_DM + initr_dm, +#endif initr_serial, initr_announce, INIT_FUNC_WATCHDOG_RESET @@ -762,12 +771,6 @@ init_fnc_t init_sequence_r[] = { #endif #ifdef CONFIG_WINBOND_83C553 initr_w83c553f, -#endif - initr_barrier, - initr_malloc, - bootstage_relocate, -#ifdef CONFIG_DM - initr_dm, #endif #ifdef CONFIG_ARCH_EARLY_INIT_R arch_early_init_r, @@ -818,7 +821,9 @@ init_fnc_t init_sequence_r[] = { */ initr_pci, #endif +#ifndef CONFIG_DM_SERIAL stdio_init, +#endif initr_jumptable, #ifdef CONFIG_API initr_api, -- cgit v1.3.1 From 9fb02491fe96991cbedc49c7ebe5cdd271d1b6a7 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 3 Sep 2014 17:37:01 -0600 Subject: dm: Make driver model available before board_init() For some boards board_init() will change GPIOs, so we need to have driver model available before then. Adjust the board init to arrange this, but enable it for driver model only, just to be safe. This does create additional #ifdef logic, but it is safer than trying to make a pervasive change which may cause some boards to break. Signed-off-by: Simon Glass --- common/board_r.c | 24 +++++++++++------------- common/stdio.c | 18 ++++++++++++++++-- include/stdio_dev.h | 24 +++++++++++++++++++++++- 3 files changed, 50 insertions(+), 16 deletions(-) (limited to 'common') diff --git a/common/board_r.c b/common/board_r.c index 64beae5f348..6ac2b7e1601 100644 --- a/common/board_r.c +++ b/common/board_r.c @@ -715,6 +715,15 @@ init_fnc_t init_sequence_r[] = { /* TODO: could x86/PPC have this also perhaps? */ #ifdef CONFIG_ARM initr_caches, +#endif + initr_reloc_global_data, + initr_barrier, + initr_malloc, + bootstage_relocate, +#ifdef CONFIG_DM + initr_dm, +#endif +#ifdef CONFIG_ARM board_init, /* Setup chipselects */ #endif /* @@ -726,16 +735,7 @@ init_fnc_t init_sequence_r[] = { #ifdef CONFIG_CLOCKS set_cpu_clk_info, /* Setup clock information */ #endif - initr_reloc_global_data, - initr_barrier, - initr_malloc, - bootstage_relocate, -#ifdef CONFIG_DM_SERIAL - stdio_init, -#endif -#ifdef CONFIG_DM - initr_dm, -#endif + stdio_init_tables, initr_serial, initr_announce, INIT_FUNC_WATCHDOG_RESET @@ -821,9 +821,7 @@ init_fnc_t init_sequence_r[] = { */ initr_pci, #endif -#ifndef CONFIG_DM_SERIAL - stdio_init, -#endif + stdio_add_devices, initr_jumptable, #ifdef CONFIG_API initr_api, diff --git a/common/stdio.c b/common/stdio.c index 692ca7f1cdf..c878103a482 100644 --- a/common/stdio.c +++ b/common/stdio.c @@ -215,7 +215,7 @@ int stdio_deregister(const char *devname) } #endif /* CONFIG_SYS_STDIO_DEREGISTER */ -int stdio_init (void) +int stdio_init_tables(void) { #if defined(CONFIG_NEEDS_MANUAL_RELOC) /* already relocated for current ARM implementation */ @@ -232,6 +232,11 @@ int stdio_init (void) /* Initialize the list */ INIT_LIST_HEAD(&(devs.list)); + return 0; +} + +int stdio_add_devices(void) +{ #ifdef CONFIG_SYS_I2C i2c_init_all(); #else @@ -265,5 +270,14 @@ int stdio_init (void) #ifdef CONFIG_CBMEM_CONSOLE cbmemc_init(); #endif - return (0); + + return 0; +} + +int stdio_init(void) +{ + stdio_init_tables(); + stdio_add_devices(); + + return 0; } diff --git a/include/stdio_dev.h b/include/stdio_dev.h index a7d0825c7e5..268de8ea700 100644 --- a/include/stdio_dev.h +++ b/include/stdio_dev.h @@ -78,7 +78,29 @@ extern char *stdio_names[MAX_FILES]; */ int stdio_register (struct stdio_dev * dev); int stdio_register_dev(struct stdio_dev *dev, struct stdio_dev **devp); -int stdio_init (void); + +/** + * stdio_init_tables() - set up stdio tables ready for devices + * + * This does not add any devices, but just prepares stdio for use. + */ +int stdio_init_tables(void); + +/** + * stdio_add_devices() - Add stdio devices to the table + * + * This makes calls to all the various subsystems that use stdio, to make + * them register with stdio. + */ +int stdio_add_devices(void); + +/** + * stdio_init() - Sets up stdio ready for use + * + * This calls stdio_init_tables() and stdio_add_devices() + */ +int stdio_init(void); + void stdio_print_current_devices(void); #ifdef CONFIG_SYS_STDIO_DEREGISTER int stdio_deregister(const char *devname); -- cgit v1.3.1 From 5d69a5d178a1fc3874b8d18e5be3e520f6acaca5 Mon Sep 17 00:00:00 2001 From: Vasili Galka Date: Tue, 26 Aug 2014 13:45:48 +0300 Subject: Fix a few printf argument verification warnings The parameters of size_t type shall be formatted using "%zu" and not using "%d". Precision argument for the "%.*s" parameters shall be of int type. Signed-off-by: Vasili Galka --- common/bouncebuf.c | 2 +- common/cmd_mtdparts.c | 4 ++-- common/spl/spl.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'common') diff --git a/common/bouncebuf.c b/common/bouncebuf.c index 9eece6d758b..054d9e0302c 100644 --- a/common/bouncebuf.c +++ b/common/bouncebuf.c @@ -23,7 +23,7 @@ static int addr_aligned(struct bounce_buffer *state) /* Check if length is aligned */ if (state->len != state->len_aligned) { - debug("Unaligned buffer length %d\n", state->len); + debug("Unaligned buffer length %zu\n", state->len); return 0; } diff --git a/common/cmd_mtdparts.c b/common/cmd_mtdparts.c index 3cb0571df39..422c0695138 100644 --- a/common/cmd_mtdparts.c +++ b/common/cmd_mtdparts.c @@ -862,7 +862,7 @@ static int device_parse(const char *const mtd_dev, const char **ret, struct mtd_ debug("dev type = %d (%s), dev num = %d, mtd-id = %s\n", id->type, MTD_DEV_TYPE(id->type), id->num, id->mtd_id); - debug("parsing partitions %.*s\n", (pend ? pend - p : strlen(p)), p); + debug("parsing partitions %.*s\n", (int)(pend ? pend - p : strlen(p)), p); /* parse partitions */ @@ -1007,7 +1007,7 @@ static struct mtdids* id_find_by_mtd_id(const char *mtd_id, unsigned int mtd_id_ list_for_each(entry, &mtdids) { id = list_entry(entry, struct mtdids, link); - debug("entry: '%s' (len = %d)\n", + debug("entry: '%s' (len = %zu)\n", id->mtd_id, strlen(id->mtd_id)); if (mtd_id_len != strlen(id->mtd_id)) diff --git a/common/spl/spl.c b/common/spl/spl.c index 774fdad2523..b16664f8454 100644 --- a/common/spl/spl.c +++ b/common/spl/spl.c @@ -86,7 +86,7 @@ void spl_parse_image_header(const struct image_header *header) spl_image.os = image_get_os(header); spl_image.name = image_get_name(header); debug("spl: payload image: %.*s load addr: 0x%x size: %d\n", - sizeof(spl_image.name), spl_image.name, + (int)sizeof(spl_image.name), spl_image.name, spl_image.load_addr, spl_image.size); } else { /* Signature not found - assume u-boot.bin */ -- cgit v1.3.1 From f9f040b21587ec884ff761cfa2f2fb66cc5157d1 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Mon, 1 Sep 2014 21:48:07 +0800 Subject: kgdb: Remove first_entry for kgdb There are two ways to run into handle_exception, run command 'kgdb' and encounter a breakpoint which triggers exception handling. The origin source code only saves regs when first run command 'kgdb'. Take the following for example, When run 'kgdb', regs is saved to entry_regs. When run 'bootz', regs is not saved. However, if we set a breakpoint, then continue. When breakpoint is reached, run `quit`, and Now return to the instruction which follows kgdb, but not bootz.This may cause errors. So, save regs for each handle_exception call to return to the correct place. Example: Target | Host =>kgdb | (gdb)b bootz | (gdb)c =>bootz | | (gdb)Here stop because of breakpoint | (gdb)q Signed-off-by: Peng Fan --- common/kgdb.c | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) (limited to 'common') diff --git a/common/kgdb.c b/common/kgdb.c index 8a621ad1fc7..d357463695f 100644 --- a/common/kgdb.c +++ b/common/kgdb.c @@ -103,7 +103,7 @@ static char remcomOutBuffer[BUFMAX]; static char remcomRegBuffer[BUFMAX]; static int initialized = 0; -static int kgdb_active = 0, first_entry = 1; +static int kgdb_active; static struct pt_regs entry_regs; static long error_jmp_buf[BUFMAX/2]; static int longjmp_on_fault = 0; @@ -348,16 +348,7 @@ handle_exception (struct pt_regs *regs) kgdb_enter(regs, &kd); - if (first_entry) { - /* - * the first time we enter kgdb, we save the processor - * state so that we can return to the monitor if the - * remote end quits gdb (or at least, tells us to quit - * with the 'k' packet) - */ - entry_regs = *regs; - first_entry = 0; - } + entry_regs = *regs; ptr = remcomOutBuffer; @@ -459,7 +450,6 @@ handle_exception (struct pt_regs *regs) case 'k': /* kill the program, actually return to monitor */ kd.extype = KGDBEXIT_KILL; *regs = entry_regs; - first_entry = 1; goto doexit; case 'C': /* CSS continue with signal SS */ -- cgit v1.3.1 From 5a8608e586bd959bde8bc267e14c36768ab956b5 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Thu, 4 Sep 2014 00:38:26 +0900 Subject: cmd_mem: add static to internally used functions Signed-off-by: Masahiro Yamada Acked-by: Simon Glass --- common/cmd_mem.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'common') diff --git a/common/cmd_mem.c b/common/cmd_mem.c index 1febddb916c..bfca59e351f 100644 --- a/common/cmd_mem.c +++ b/common/cmd_mem.c @@ -215,7 +215,7 @@ static int do_mem_mw(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) } #ifdef CONFIG_MX_CYCLIC -int do_mem_mdc ( cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +static int do_mem_mdc(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { int i; ulong count; @@ -242,7 +242,7 @@ int do_mem_mdc ( cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) return 0; } -int do_mem_mwc ( cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +static int do_mem_mwc(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { int i; ulong count; @@ -595,7 +595,8 @@ static int do_mem_loop(cmd_tbl_t *cmdtp, int flag, int argc, } #ifdef CONFIG_LOOPW -int do_mem_loopw (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +static int do_mem_loopw(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) { ulong addr, length, i, bytes; int size; -- cgit v1.3.1 From b4e4bbe5ab1d0b990ec36586b61114eeb8b5b939 Mon Sep 17 00:00:00 2001 From: Steve Rae Date: Wed, 3 Sep 2014 10:05:51 -0700 Subject: add code to handle Android sparse image format 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 --- common/aboot.c | 2643 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 2643 insertions(+) create mode 100644 common/aboot.c (limited to 'common') diff --git a/common/aboot.c b/common/aboot.c new file mode 100644 index 00000000000..3b5092d20bd --- /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 +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if DEVICE_TREE +#include +#include +#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; chunktotal_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 size in hex + * fastboot getvar partition_type:: 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 -- cgit v1.3.1 From 20465c73b47b65040625cffa8764d3cf62671820 Mon Sep 17 00:00:00 2001 From: Steve Rae Date: Wed, 3 Sep 2014 10:05:52 -0700 Subject: update code which handles Android sparse image format - remove unnecessary functions Signed-off-by: Steve Rae --- common/aboot.c | 2438 -------------------------------------------------------- 1 file changed, 2438 deletions(-) (limited to 'common') diff --git a/common/aboot.c b/common/aboot.c index 3b5092d20bd..a302c92627f 100644 --- a/common/aboot.c +++ b/common/aboot.c @@ -30,1819 +30,6 @@ * */ -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if DEVICE_TREE -#include -#include -#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; @@ -2016,628 +203,3 @@ void cmd_flash_mmc_sparse_img(const char *arg, void *data, unsigned sz) 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 size in hex - * fastboot getvar partition_type:: 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 -- cgit v1.3.1 From 1c39d856db8b3e32fe3d5b820fbfc8ba57ab8dd7 Mon Sep 17 00:00:00 2001 From: Steve Rae Date: Wed, 3 Sep 2014 10:05:53 -0700 Subject: cleanup code which handles the Android sparse image format - port dprintf() to debug() - update formatting Signed-off-by: Steve Rae --- common/aboot.c | 97 +++++++++++++++++++++++++++++++++------------------------- 1 file changed, 56 insertions(+), 41 deletions(-) (limited to 'common') diff --git a/common/aboot.c b/common/aboot.c index a302c92627f..3611feb1c39 100644 --- a/common/aboot.c +++ b/common/aboot.c @@ -28,6 +28,9 @@ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * + * NOTE: + * Although it is very similar, this license text is not identical + * to the "BSD-3-Clause", therefore, DO NOT MODIFY THIS LICENSE TEXT! */ void cmd_flash_mmc_sparse_img(const char *arg, void *data, unsigned sz) @@ -70,23 +73,24 @@ void cmd_flash_mmc_sparse_img(const char *arg, void *data, unsigned sz) } data += sparse_header->file_hdr_sz; - if(sparse_header->file_hdr_sz > sizeof(sparse_header_t)) + if (sparse_header->file_hdr_sz > sizeof(sparse_header_t)) { - /* Skip the remaining bytes in a header that is longer than + /* + * 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); + debug("=== Sparse Image Header ===\n"); + debug("magic: 0x%x\n", sparse_header->magic); + debug("major_version: 0x%x\n", sparse_header->major_version); + debug("minor_version: 0x%x\n", sparse_header->minor_version); + debug("file_hdr_sz: %d\n", sparse_header->file_hdr_sz); + debug("chunk_hdr_sz: %d\n", sparse_header->chunk_hdr_sz); + debug("blk_sz: %d\n", sparse_header->blk_sz); + debug("total_blks: %d\n", sparse_header->total_blks); + debug("total_chunks: %d\n", sparse_header->total_chunks); /* Start processing chunks */ for (chunk=0; chunktotal_chunks; chunk++) @@ -95,33 +99,37 @@ void cmd_flash_mmc_sparse_img(const char *arg, void *data, unsigned sz) 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); + debug("=== Chunk Header ===\n"); + debug("chunk_type: 0x%x\n", chunk_header->chunk_type); + debug("chunk_data_sz: 0x%x\n", chunk_header->chunk_sz); + debug("total_size: 0x%x\n", chunk_header->total_sz); - if(sparse_header->chunk_hdr_sz > sizeof(chunk_header_t)) + if (sparse_header->chunk_hdr_sz > sizeof(chunk_header_t)) { - /* Skip the remaining bytes in a header that is longer than - * we expected. + /* + * Skip the remaining bytes in a header that is longer + * than we expected. */ - data += (sparse_header->chunk_hdr_sz - sizeof(chunk_header_t)); + 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)) + if (chunk_header->total_sz != + (sparse_header->chunk_hdr_sz + chunk_data_sz)) { - fastboot_fail("Bogus chunk size for chunk type Raw"); + 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)) + if (mmc_write(ptn + + ((uint64_t)total_blocks * + sparse_header->blk_sz), + chunk_data_sz, (unsigned int *)data)) { fastboot_fail("flash write failure"); return; @@ -131,17 +139,22 @@ void cmd_flash_mmc_sparse_img(const char *arg, void *data, unsigned sz) break; case CHUNK_TYPE_FILL: - if(chunk_header->total_sz != (sparse_header->chunk_hdr_sz + - sizeof(uint32_t))) + if (chunk_header->total_sz != + (sparse_header->chunk_hdr_sz + sizeof(uint32_t))) { - fastboot_fail("Bogus chunk size for chunk type FILL"); + fastboot_fail( + "Bogus chunk size for chunk type FILL"); return; } - fill_buf = (uint32_t *)memalign(CACHE_LINE, ROUNDUP(sparse_header->blk_sz, CACHE_LINE)); + 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"); + fastboot_fail( + "Malloc failed for: CHUNK_TYPE_FILL"); return; } @@ -156,9 +169,10 @@ void cmd_flash_mmc_sparse_img(const char *arg, void *data, unsigned sz) 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)) + 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); @@ -176,9 +190,11 @@ void cmd_flash_mmc_sparse_img(const char *arg, void *data, unsigned sz) break; case CHUNK_TYPE_CRC: - if(chunk_header->total_sz != sparse_header->chunk_hdr_sz) + if (chunk_header->total_sz != + sparse_header->chunk_hdr_sz) { - fastboot_fail("Bogus chunk size for chunk type Dont Care"); + fastboot_fail( + "Bogus chunk size for chunk type Dont Care"); return; } total_blocks += chunk_header->chunk_sz; @@ -186,19 +202,18 @@ void cmd_flash_mmc_sparse_img(const char *arg, void *data, unsigned sz) break; default: - dprintf(CRITICAL, "Unkown chunk type: %x\n",chunk_header->chunk_type); + debug("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); + debug("Wrote %d blocks, expected to write %d blocks\n", + total_blocks, sparse_header->total_blks); - if(total_blocks != sparse_header->total_blks) - { + if (total_blocks != sparse_header->total_blks) fastboot_fail("sparse image write failure"); - } fastboot_okay(""); return; -- cgit v1.3.1 From e6ca1ad604419619e2e6ba16a6e43cf15ff07fb1 Mon Sep 17 00:00:00 2001 From: Steve Rae Date: Wed, 3 Sep 2014 10:05:54 -0700 Subject: implement the Android sparse image format update to provide usable implementation to U-Boot Signed-off-by: Steve Rae --- common/aboot.c | 129 +++++++++++++++++++++++++++++--------------------- include/aboot.h | 28 +++++++++++ include/sparse_defs.h | 7 +++ 3 files changed, 111 insertions(+), 53 deletions(-) create mode 100644 include/aboot.h create mode 100644 include/sparse_defs.h (limited to 'common') diff --git a/common/aboot.c b/common/aboot.c index 3611feb1c39..d5c464bd7da 100644 --- a/common/aboot.c +++ b/common/aboot.c @@ -3,6 +3,7 @@ * All rights reserved. * * Copyright (c) 2009-2014, The Linux Foundation. All rights reserved. + * Portions Copyright 2014 Broadcom Corporation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -33,44 +34,32 @@ * to the "BSD-3-Clause", therefore, DO NOT MODIFY THIS LICENSE TEXT! */ -void cmd_flash_mmc_sparse_img(const char *arg, void *data, unsigned sz) +#include +#include +#include +#include +#include +#include + +void write_sparse_image(block_dev_desc_t *dev_desc, + disk_partition_t *info, const char *part_name, + void *data, unsigned sz) { + lbaint_t blk; + lbaint_t blkcnt; + lbaint_t blks; + uint32_t bytes_written = 0; 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)) @@ -92,17 +81,31 @@ void cmd_flash_mmc_sparse_img(const char *arg, void *data, unsigned sz) debug("total_blks: %d\n", sparse_header->total_blks); debug("total_chunks: %d\n", sparse_header->total_chunks); + /* verify sparse_header->blk_sz is an exact multiple of info->blksz */ + if (sparse_header->blk_sz != + (sparse_header->blk_sz & ~(info->blksz - 1))) { + printf("%s: Sparse image block size issue [%u]\n", + __func__, sparse_header->blk_sz); + fastboot_fail("sparse image block size issue"); + return; + } + + puts("Flashing Sparse Image\n"); + /* Start processing chunks */ + blk = info->start; for (chunk=0; chunktotal_chunks; chunk++) { /* Read and skip over chunk header */ chunk_header = (chunk_header_t *) data; data += sizeof(chunk_header_t); - debug("=== Chunk Header ===\n"); - debug("chunk_type: 0x%x\n", chunk_header->chunk_type); - debug("chunk_data_sz: 0x%x\n", chunk_header->chunk_sz); - debug("total_size: 0x%x\n", chunk_header->total_sz); + if (chunk_header->chunk_type != CHUNK_TYPE_RAW) { + debug("=== Chunk Header ===\n"); + debug("chunk_type: 0x%x\n", chunk_header->chunk_type); + debug("chunk_data_sz: 0x%x\n", chunk_header->chunk_sz); + debug("total_size: 0x%x\n", chunk_header->total_sz); + } if (sparse_header->chunk_hdr_sz > sizeof(chunk_header_t)) { @@ -115,6 +118,7 @@ void cmd_flash_mmc_sparse_img(const char *arg, void *data, unsigned sz) } chunk_data_sz = sparse_header->blk_sz * chunk_header->chunk_sz; + blkcnt = chunk_data_sz / info->blksz; switch (chunk_header->chunk_type) { case CHUNK_TYPE_RAW: @@ -126,14 +130,25 @@ void cmd_flash_mmc_sparse_img(const char *arg, void *data, unsigned sz) return; } - if (mmc_write(ptn + - ((uint64_t)total_blocks * - sparse_header->blk_sz), - chunk_data_sz, (unsigned int *)data)) - { + if (blk + blkcnt > info->start + info->size) { + printf( + "%s: Request would exceed partition size!\n", + __func__); + fastboot_fail( + "Request would exceed partition size!"); + return; + } + + blks = dev_desc->block_write(dev_desc->dev, blk, blkcnt, + data); + if (blks != blkcnt) { + printf("%s: Write failed " LBAFU "\n", + __func__, blks); fastboot_fail("flash write failure"); return; } + blk += blkcnt; + bytes_written += blkcnt * info->blksz; total_blocks += chunk_header->chunk_sz; data += chunk_data_sz; break; @@ -148,9 +163,9 @@ void cmd_flash_mmc_sparse_img(const char *arg, void *data, unsigned sz) } fill_buf = (uint32_t *) - memalign(CACHE_LINE, - ROUNDUP(sparse_header->blk_sz, - CACHE_LINE)); + memalign(ARCH_DMA_MINALIGN, + ROUNDUP(info->blksz, + ARCH_DMA_MINALIGN)); if (!fill_buf) { fastboot_fail( @@ -160,27 +175,34 @@ void cmd_flash_mmc_sparse_img(const char *arg, void *data, unsigned sz) 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++) - { + for (i = 0; i < (info->blksz / sizeof(fill_val)); i++) fill_buf[i] = fill_val; + + if (blk + blkcnt > info->start + info->size) { + printf( + "%s: Request would exceed partition size!\n", + __func__); + fastboot_fail( + "Request would exceed partition size!"); + return; } - 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)) - { + for (i = 0; i < blkcnt; i++) { + blks = dev_desc->block_write(dev_desc->dev, + blk, 1, fill_buf); + if (blks != 1) { + printf( + "%s: Write failed, block # " LBAFU "\n", + __func__, blkcnt); fastboot_fail("flash write failure"); free(fill_buf); return; } - - total_blocks++; + blk++; } + bytes_written += blkcnt * info->blksz; + total_blocks += chunk_data_sz / sparse_header->blk_sz; free(fill_buf); break; @@ -189,7 +211,7 @@ void cmd_flash_mmc_sparse_img(const char *arg, void *data, unsigned sz) total_blocks += chunk_header->chunk_sz; break; - case CHUNK_TYPE_CRC: + case CHUNK_TYPE_CRC32: if (chunk_header->total_sz != sparse_header->chunk_hdr_sz) { @@ -202,8 +224,8 @@ void cmd_flash_mmc_sparse_img(const char *arg, void *data, unsigned sz) break; default: - debug("Unkown chunk type: %x\n", - chunk_header->chunk_type); + printf("%s: Unknown chunk type: %x\n", __func__, + chunk_header->chunk_type); fastboot_fail("Unknown chunk type"); return; } @@ -211,6 +233,7 @@ void cmd_flash_mmc_sparse_img(const char *arg, void *data, unsigned sz) debug("Wrote %d blocks, expected to write %d blocks\n", total_blocks, sparse_header->total_blks); + printf("........ wrote %u bytes to '%s'\n", bytes_written, part_name); if (total_blocks != sparse_header->total_blks) fastboot_fail("sparse image write failure"); diff --git a/include/aboot.h b/include/aboot.h new file mode 100644 index 00000000000..30e4d36df8b --- /dev/null +++ b/include/aboot.h @@ -0,0 +1,28 @@ +/* + * Copyright 2014 Broadcom Corporation. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include + +#define ROUNDUP(x, y) (((x) + ((y) - 1)) & ~((y) - 1)) + +void fastboot_fail(const char *s); +void fastboot_okay(const char *s); + +static inline int is_sparse_image(void *buf) +{ + sparse_header_t *s_header = (sparse_header_t *)buf; + + if ((le32_to_cpu(s_header->magic) == SPARSE_HEADER_MAGIC) && + (le16_to_cpu(s_header->major_version) == 1)) + return 1; + + return 0; +} + +void write_sparse_image(block_dev_desc_t *dev_desc, + disk_partition_t *info, const char *part_name, + void *data, unsigned sz); diff --git a/include/sparse_defs.h b/include/sparse_defs.h new file mode 100644 index 00000000000..d0612c94e5d --- /dev/null +++ b/include/sparse_defs.h @@ -0,0 +1,7 @@ +/* + * Copyright 2014 Broadcom Corporation. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include -- cgit v1.3.1 From ec3b48201d0338efa7f3ce4173ffe69e573e2511 Mon Sep 17 00:00:00 2001 From: Gabriel Huau Date: Wed, 3 Sep 2014 13:57:54 -0700 Subject: common: fix include guards for CONFIG_MP This was breaking the build for some boards: MPC8536DS MPC8536DS_36BIT MPC8536DS_SDCARD MPC8536DS_SPIFLASH qemu-ppce500 Include only these features for some PPC boards if the configuration for MultiProcessor is enabled. Signed-off-by: Gabriel Huau Cc: Tom Rini Cc: York Sun Acked-by: York Sun --- common/board_f.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'common') diff --git a/common/board_f.c b/common/board_f.c index ea33eadc16e..5f33bce4a2b 100644 --- a/common/board_f.c +++ b/common/board_f.c @@ -34,7 +34,7 @@ #ifdef CONFIG_MPC5xxx #include #endif -#if (defined(CONFIG_MPC86xx) || defined(CONFIG_E500)) +#if defined(CONFIG_MP) && (defined(CONFIG_MPC86xx) || defined(CONFIG_E500)) #include #endif @@ -392,7 +392,7 @@ static int setup_dest_addr(void) gd->ram_top = board_get_usable_ram_top(gd->mon_len); gd->relocaddr = gd->ram_top; debug("Ram top: %08lX\n", (ulong)gd->ram_top); -#if (defined(CONFIG_MPC86xx) || defined(CONFIG_E500)) +#if defined(CONFIG_MP) && (defined(CONFIG_MPC86xx) || defined(CONFIG_E500)) /* * We need to make sure the location we intend to put secondary core * boot code is reserved and not used by any part of u-boot -- cgit v1.3.1 From c970dffedb9f7bf76d67157c8ceba64496b0c64a Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sat, 6 Sep 2014 23:39:00 +0900 Subject: generic_board: do not set gd->fdt_blob unless CONFIG_OF_CONTROL=y gd->fdt_blob is used for FDT control of U-Boot. If CONFIG_OF_CONTROL is not defined, it is useless. Signed-off-by: Masahiro Yamada Cc: Simon Glass Acked-by: Simon Glass --- common/board_f.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'common') diff --git a/common/board_f.c b/common/board_f.c index 5f33bce4a2b..e6aa298d5a4 100644 --- a/common/board_f.c +++ b/common/board_f.c @@ -341,21 +341,23 @@ static int setup_ram_buf(void) static int setup_fdt(void) { -#ifdef CONFIG_OF_EMBED +#ifdef CONFIG_OF_CONTROL +# ifdef CONFIG_OF_EMBED /* Get a pointer to the FDT */ gd->fdt_blob = __dtb_dt_begin; -#elif defined CONFIG_OF_SEPARATE +# elif defined CONFIG_OF_SEPARATE /* FDT is at end of image */ gd->fdt_blob = (ulong *)&_end; -#elif defined(CONFIG_OF_HOSTFILE) +# elif defined(CONFIG_OF_HOSTFILE) if (read_fdt_from_file()) { puts("Failed to read control FDT\n"); return -1; } -#endif +# endif /* Allow the early environment to override the fdt address */ gd->fdt_blob = (void *)getenv_ulong("fdtcontroladdr", 16, (uintptr_t)gd->fdt_blob); +#endif return 0; } -- cgit v1.3.1