X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=arch%2Farm%2Flib%2Fbootm.c;h=f9ed7fe38ab8d790a0b712341a5af2ef576c0ed8;hb=a60d94b204412732409e70cb15236bd96d4da7d9;hp=eefb456efb50257283a3d215a98404ac0c23d504;hpb=1a4596601fd395f3afb8f82f3f840c5e00bdd57a;p=oweals%2Fu-boot.git diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c index eefb456efb..f9ed7fe38a 100644 --- a/arch/arm/lib/bootm.c +++ b/arch/arm/lib/bootm.c @@ -18,9 +18,17 @@ #include #include #include +#include #include #include +#include #include +#include +#include + +#ifdef CONFIG_ARMV7_NONSEC +#include +#endif DECLARE_GLOBAL_DATA_PTR; @@ -67,8 +75,7 @@ static void announce_and_cleanup(int fake) "(fake run for tracing)" : ""); bootstage_mark_name(BOOTSTAGE_ID_BOOTM_HANDOFF, "start_kernel"); #ifdef CONFIG_BOOTSTAGE_FDT - if (flag == BOOTM_STATE_OS_FAKE_GO) - bootstage_fdt_add_report(); + bootstage_fdt_add_report(); #endif #ifdef CONFIG_BOOTSTAGE_REPORT bootstage_report(); @@ -181,6 +188,18 @@ static void setup_end_tag(bd_t *bd) __weak void setup_board_tags(struct tag **in_params) {} +#ifdef CONFIG_ARM64 +static void do_nonsec_virt_switch(void) +{ + smp_kick_all_cpus(); + dcache_disable(); /* flush cache before swtiching to EL2 */ + armv8_switch_to_el2(); +#ifdef CONFIG_ARMV8_SWITCH_TO_EL1 + armv8_switch_to_el1(); +#endif +} +#endif + /* Subcommand: PREP */ static void boot_prep_linux(bootm_headers_t *images) { @@ -206,7 +225,17 @@ static void boot_prep_linux(bootm_headers_t *images) if (BOOTM_ENABLE_MEMORY_TAGS) setup_memory_tags(gd->bd); if (BOOTM_ENABLE_INITRD_TAG) { - if (images->rd_start && images->rd_end) { + /* + * In boot_ramdisk_high(), it may relocate ramdisk to + * a specified location. And set images->initrd_start & + * images->initrd_end to relocated ramdisk's start/end + * addresses. So use them instead of images->rd_start & + * images->rd_end when possible. + */ + if (images->initrd_start && images->initrd_end) { + setup_initrd_tag(gd->bd, images->initrd_start, + images->initrd_end); + } else if (images->rd_start && images->rd_end) { setup_initrd_tag(gd->bd, images->rd_start, images->rd_end); } @@ -219,9 +248,48 @@ static void boot_prep_linux(bootm_headers_t *images) } } +#ifdef CONFIG_ARMV7_NONSEC +bool armv7_boot_nonsec(void) +{ + char *s = getenv("bootm_boot_mode"); +#ifdef CONFIG_ARMV7_BOOT_SEC_DEFAULT + bool nonsec = false; +#else + bool nonsec = true; +#endif + + if (s && !strcmp(s, "sec")) + nonsec = false; + + if (s && !strcmp(s, "nonsec")) + nonsec = true; + + return nonsec; +} +#endif + /* Subcommand: GO */ static void boot_jump_linux(bootm_headers_t *images, int flag) { +#ifdef CONFIG_ARM64 + void (*kernel_entry)(void *fdt_addr, void *res0, void *res1, + void *res2); + int fake = (flag & BOOTM_STATE_OS_FAKE_GO); + + kernel_entry = (void (*)(void *fdt_addr, void *res0, void *res1, + void *res2))images->ep; + + debug("## Transferring control to Linux (at address %lx)...\n", + (ulong) kernel_entry); + bootstage_mark(BOOTSTAGE_ID_RUN_OS); + + announce_and_cleanup(fake); + + if (!fake) { + do_nonsec_virt_switch(); + kernel_entry(images->ft_addr, NULL, NULL, NULL); + } +#else unsigned long machid = gd->bd->bi_arch_number; char *s; void (*kernel_entry)(int zero, int arch, uint params); @@ -232,7 +300,10 @@ static void boot_jump_linux(bootm_headers_t *images, int flag) s = getenv("machid"); if (s) { - strict_strtoul(s, 16, &machid); + if (strict_strtoul(s, 16, &machid) < 0) { + debug("strict_strtoul failed!\n"); + return; + } printf("Using machid 0x%lx from environment\n", machid); } @@ -246,8 +317,17 @@ static void boot_jump_linux(bootm_headers_t *images, int flag) else r2 = gd->bd->bi_boot_params; - if (!fake) - kernel_entry(0, machid, r2); + if (!fake) { +#ifdef CONFIG_ARMV7_NONSEC + if (armv7_boot_nonsec()) { + armv7_init_nonsec(); + secure_ram_addr(_do_nonsec_entry)(kernel_entry, + 0, machid, r2); + } else +#endif + kernel_entry(0, machid, r2); + } +#endif } /* Main Entry point for arm bootm implementation @@ -256,7 +336,8 @@ static void boot_jump_linux(bootm_headers_t *images, int flag) * DIFFERENCE: Instead of calling prep and go at the end * they are called if subcommand is equal 0. */ -int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images) +int do_bootm_linux(int flag, int argc, char * const argv[], + bootm_headers_t *images) { /* No need for those on ARM */ if (flag & BOOTM_STATE_OS_BD_T || flag & BOOTM_STATE_OS_CMDLINE) @@ -277,34 +358,27 @@ int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images) return 0; } -#ifdef CONFIG_CMD_BOOTZ - -struct zimage_header { - uint32_t code[9]; - uint32_t zi_magic; - uint32_t zi_start; - uint32_t zi_end; -}; - -#define LINUX_ARM_ZIMAGE_MAGIC 0x016f2818 - -int bootz_setup(ulong image, ulong *start, ulong *end) +#if defined(CONFIG_BOOTM_VXWORKS) +void boot_prep_vxworks(bootm_headers_t *images) { - struct zimage_header *zi; - - zi = (struct zimage_header *)map_sysmem(image, 0); - if (zi->zi_magic != LINUX_ARM_ZIMAGE_MAGIC) { - puts("Bad Linux ARM zImage magic!\n"); - return 1; +#if defined(CONFIG_OF_LIBFDT) + int off; + + if (images->ft_addr) { + off = fdt_path_offset(images->ft_addr, "/memory"); + if (off < 0) { +#ifdef CONFIG_ARCH_FIXUP_FDT + if (arch_fixup_fdt(images->ft_addr)) + puts("## WARNING: fixup memory failed!\n"); +#endif + } } - - *start = zi->zi_start; - *end = zi->zi_end; - - printf("Kernel image @ %#08lx [ %#08lx - %#08lx ]\n", image, *start, - *end); - - return 0; +#endif + cleanup_before_linux(); } - -#endif /* CONFIG_CMD_BOOTZ */ +void boot_jump_vxworks(bootm_headers_t *images) +{ + /* ARM VxWorks requires device tree physical address to be passed */ + ((void (*)(void *))images->ep)(images->ft_addr); +} +#endif