X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=arch%2Farm%2Flib%2Fbootm.c;h=b27266c7a1933c625031e8b67ddbb479d1cb74bc;hb=83d290c56fab2d38cd1ab4c4cc7099559c1d5046;hp=2d6b6761548a8e3bcb7baaffdbe0343b7acc8334;hpb=00956eb5f313d0a62c39f4fa642ffbaa85cc955c;p=platform%2Fkernel%2Fu-boot.git diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c index 2d6b676..b27266c 100644 --- a/arch/arm/lib/bootm.c +++ b/arch/arm/lib/bootm.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* Copyright (C) 2011 * Corscience GmbH & Co. KG - Simon Schwarz * - Added prep subcommand support @@ -8,16 +9,17 @@ * Marius Groeger * * Copyright (C) 2001 Erik Mouw (J.A.K.Mouw@its.tudelft.nl) - * - * SPDX-License-Identifier: GPL-2.0+ */ #include #include +#include +#include #include #include #include -#include +#include +#include #include #include #include @@ -25,9 +27,10 @@ #include #include -#if defined(CONFIG_ARMV7_NONSEC) || defined(CONFIG_ARMV7_VIRT) +#ifdef CONFIG_ARMV7_NONSEC #include #endif +#include DECLARE_GLOBAL_DATA_PTR; @@ -43,7 +46,8 @@ static ulong get_sp(void) void arch_lmb_reserve(struct lmb *lmb) { - ulong sp; + ulong sp, bank_end; + int bank; /* * Booting a (Linux) kernel image @@ -59,8 +63,20 @@ void arch_lmb_reserve(struct lmb *lmb) /* adjust sp by 4K to be safe */ sp -= 4096; - lmb_reserve(lmb, sp, - gd->bd->bi_dram[0].start + gd->bd->bi_dram[0].size - sp); + for (bank = 0; bank < CONFIG_NR_DRAM_BANKS; bank++) { + if (sp < gd->bd->bi_dram[bank].start) + continue; + bank_end = gd->bd->bi_dram[bank].start + + gd->bd->bi_dram[bank].size; + if (sp >= bank_end) + continue; + lmb_reserve(lmb, sp, bank_end - sp); + break; + } +} + +__weak void board_quiesce_devices(void) +{ } /** @@ -83,6 +99,16 @@ static void announce_and_cleanup(int fake) #ifdef CONFIG_USB_DEVICE udc_disconnect(); #endif + + board_quiesce_devices(); + + /* + * Call remove function of all devices with a removal flag set. + * This may be useful for last-stage operations, like cancelling + * of DMA operation or releasing device internal buffers. + */ + dm_remove_devices_flags(DM_REMOVE_ACTIVE_ALL); + cleanup_before_linux(); } @@ -192,17 +218,13 @@ 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) { - char *commandline = getenv("bootargs"); + char *commandline = env_get("bootargs"); if (IMAGE_ENABLE_OF_LIBFDT && images->ft_len) { #ifdef CONFIG_OF_LIBFDT @@ -224,7 +246,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); } @@ -237,15 +269,20 @@ static void boot_prep_linux(bootm_headers_t *images) } } -#if defined(CONFIG_ARMV7_NONSEC) || defined(CONFIG_ARMV7_VIRT) -bool armv7_boot_nonsec(void) +__weak bool armv7_boot_nonsec_default(void) { - char *s = getenv("bootm_boot_mode"); #ifdef CONFIG_ARMV7_BOOT_SEC_DEFAULT - bool nonsec = false; + return false; #else - bool nonsec = true; + return true; #endif +} + +#ifdef CONFIG_ARMV7_NONSEC +bool armv7_boot_nonsec(void) +{ + char *s = env_get("bootm_boot_mode"); + bool nonsec = armv7_boot_nonsec_default(); if (s && !strcmp(s, "sec")) nonsec = false; @@ -257,6 +294,28 @@ bool armv7_boot_nonsec(void) } #endif +#ifdef CONFIG_ARM64 +__weak void update_os_arch_secondary_cores(uint8_t os_arch) +{ +} + +#ifdef CONFIG_ARMV8_SWITCH_TO_EL1 +static void switch_to_el1(void) +{ + if ((IH_ARCH_DEFAULT == IH_ARCH_ARM64) && + (images.os.arch == IH_ARCH_ARM)) + armv8_switch_to_el1(0, (u64)gd->bd->bi_arch_number, + (u64)images.ft_addr, 0, + (u64)images.ep, + ES_TO_AARCH32); + else + armv8_switch_to_el1((u64)images.ft_addr, 0, 0, 0, + images.ep, + ES_TO_AARCH64); +} +#endif +#endif + /* Subcommand: GO */ static void boot_jump_linux(bootm_headers_t *images, int flag) { @@ -275,8 +334,28 @@ static void boot_jump_linux(bootm_headers_t *images, int flag) announce_and_cleanup(fake); if (!fake) { +#ifdef CONFIG_ARMV8_PSCI + armv8_setup_psci(); +#endif do_nonsec_virt_switch(); - kernel_entry(images->ft_addr, NULL, NULL, NULL); + + update_os_arch_secondary_cores(images->os.arch); + +#ifdef CONFIG_ARMV8_SWITCH_TO_EL1 + armv8_switch_to_el2((u64)images->ft_addr, 0, 0, 0, + (u64)switch_to_el1, ES_TO_AARCH64); +#else + if ((IH_ARCH_DEFAULT == IH_ARCH_ARM64) && + (images->os.arch == IH_ARCH_ARM)) + armv8_switch_to_el2(0, (u64)gd->bd->bi_arch_number, + (u64)images->ft_addr, 0, + (u64)images->ep, + ES_TO_AARCH32); + else + armv8_switch_to_el2((u64)images->ft_addr, 0, 0, 0, + images->ep, + ES_TO_AARCH64); +#endif } #else unsigned long machid = gd->bd->bi_arch_number; @@ -286,10 +365,16 @@ static void boot_jump_linux(bootm_headers_t *images, int flag) int fake = (flag & BOOTM_STATE_OS_FAKE_GO); kernel_entry = (void (*)(int, int, uint))images->ep; - - s = getenv("machid"); +#ifdef CONFIG_CPU_V7M + ulong addr = (ulong)kernel_entry | 1; + kernel_entry = (void *)addr; +#endif + s = env_get("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); } @@ -304,7 +389,7 @@ static void boot_jump_linux(bootm_headers_t *images, int flag) r2 = gd->bd->bi_boot_params; if (!fake) { -#if defined(CONFIG_ARMV7_NONSEC) || defined(CONFIG_ARMV7_VIRT) +#ifdef CONFIG_ARMV7_NONSEC if (armv7_boot_nonsec()) { armv7_init_nonsec(); secure_ram_addr(_do_nonsec_entry)(kernel_entry, @@ -344,38 +429,6 @@ int do_bootm_linux(int flag, int argc, char * const argv[], 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) -{ - 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; - } - - *start = zi->zi_start; - *end = zi->zi_end; - - printf("Kernel image @ %#08lx [ %#08lx - %#08lx ]\n", image, *start, - *end); - - return 0; -} - -#endif /* CONFIG_CMD_BOOTZ */ - #if defined(CONFIG_BOOTM_VXWORKS) void boot_prep_vxworks(bootm_headers_t *images) { @@ -394,6 +447,11 @@ void boot_prep_vxworks(bootm_headers_t *images) } void boot_jump_vxworks(bootm_headers_t *images) { +#if defined(CONFIG_ARM64) && defined(CONFIG_ARMV8_PSCI) + armv8_setup_psci(); + smp_kick_all_cpus(); +#endif + /* ARM VxWorks requires device tree physical address to be passed */ ((void (*)(void *))images->ep)(images->ft_addr); }