1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * (C) Copyright 2016 nexell
4  * jhkim <jhkim@nexell.co.kr>
5  */
6 
7 #include <common.h>
8 #include <bootm.h>
9 #include <command.h>
10 #include <environment.h>
11 #include <errno.h>
12 #include <image.h>
13 #include <fdt_support.h>
14 #include <asm/global_data.h>
15 
16 #if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_CLI_FRAMEWORK)
17 
18 DECLARE_GLOBAL_DATA_PTR;
19 
20 static bootm_headers_t linux_images;
21 
boot_go_set_os(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[],bootm_headers_t * images)22 static void boot_go_set_os(cmd_tbl_t *cmdtp, int flag, int argc,
23 			   char * const argv[],
24 			   bootm_headers_t *images)
25 {
26 	char * const img_addr = argv[0];
27 
28 	images->os.type = IH_TYPE_KERNEL;
29 	images->os.comp = IH_COMP_NONE;
30 	images->os.os = IH_OS_LINUX;
31 	images->os.load = simple_strtoul(img_addr, NULL, 16);
32 	images->ep = images->os.load;
33 #if defined(CONFIG_ARM)
34 	images->os.arch = IH_ARCH_ARM;
35 #elif defined(CONFIG_ARM64)
36 	images->os.arch = IH_ARCH_ARM64;
37 #else
38 	#error "Not support architecture ..."
39 #endif
40 	if (!IS_ENABLED(CONFIG_OF_LIBFDT) && !IS_ENABLED(CONFIG_SPL_BUILD)) {
41 		/* set DTB address for linux kernel */
42 		if (argc > 2) {
43 			unsigned long ft_addr;
44 
45 			ft_addr = simple_strtol(argv[2], NULL, 16);
46 			images->ft_addr = (char *)ft_addr;
47 
48 			/*
49 			 * if not defined IMAGE_ENABLE_OF_LIBFDT,
50 			 * must be set to fdt address
51 			 */
52 			if (!IMAGE_ENABLE_OF_LIBFDT)
53 				gd->bd->bi_boot_params = ft_addr;
54 
55 			debug("## set ft:%08lx and boot params:%08lx [control of:%s]"
56 			      "...\n", ft_addr, gd->bd->bi_boot_params,
57 			      IMAGE_ENABLE_OF_LIBFDT ? "on" : "off");
58 		}
59 	}
60 }
61 
62 #if defined(CONFIG_OF_LIBFDT) && defined(CONFIG_LMB)
boot_start_lmb(bootm_headers_t * images)63 static void boot_start_lmb(bootm_headers_t *images)
64 {
65 	ulong		mem_start;
66 	phys_size_t	mem_size;
67 
68 	lmb_init(&images->lmb);
69 
70 	mem_start = getenv_bootm_low();
71 	mem_size = getenv_bootm_size();
72 
73 	lmb_add(&images->lmb, (phys_addr_t)mem_start, mem_size);
74 
75 	arch_lmb_reserve(&images->lmb);
76 	board_lmb_reserve(&images->lmb);
77 }
78 #else
79 #define lmb_reserve(lmb, base, size)
boot_start_lmb(bootm_headers_t * images)80 static inline void boot_start_lmb(bootm_headers_t *images) { }
81 #endif
82 
do_boot_linux(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])83 int do_boot_linux(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
84 {
85 	boot_os_fn *boot_fn;
86 	bootm_headers_t *images = &linux_images;
87 	int flags;
88 	int ret;
89 
90 	boot_start_lmb(images);
91 
92 	flags  = BOOTM_STATE_START;
93 
94 	argc--; argv++;
95 	boot_go_set_os(cmdtp, flag, argc, argv, images);
96 
97 	if (IS_ENABLED(CONFIG_OF_LIBFDT)) {
98 		/* find flattened device tree */
99 		ret = boot_get_fdt(flag, argc, argv, IH_ARCH_DEFAULT, images,
100 				   &images->ft_addr, &images->ft_len);
101 		if (ret) {
102 			puts("Could not find a valid device tree\n");
103 			return 1;
104 		}
105 		set_working_fdt_addr((ulong)images->ft_addr);
106 	}
107 
108 	if (!IS_ENABLED(CONFIG_OF_LIBFDT))
109 		flags |= BOOTM_STATE_OS_GO;
110 
111 	boot_fn = do_bootm_linux;
112 	ret = boot_fn(flags, argc, argv, images);
113 
114 	if (ret == BOOTM_ERR_UNIMPLEMENTED)
115 		show_boot_progress(BOOTSTAGE_ID_DECOMP_UNIMPL);
116 	else if (ret == BOOTM_ERR_RESET)
117 		do_reset(cmdtp, flag, argc, argv);
118 
119 	return ret;
120 }
121 
122 U_BOOT_CMD(bootl, CONFIG_SYS_MAXARGS, 1, do_boot_linux,
123 	   "boot linux image from memory",
124 	   "[addr [arg ...]]\n    - boot linux image stored in memory\n"
125 	   "\tuse a '-' for the DTB address\n"
126 );
127 #endif
128 
129 #if defined(CONFIG_CMD_BOOTD) && !defined(CONFIG_CMD_BOOTM)
do_bootd(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])130 int do_bootd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
131 {
132 	return run_command(env_get("bootcmd"), flag);
133 }
134 
135 U_BOOT_CMD(boot, 1, 1, do_bootd,
136 	   "boot default, i.e., run 'bootcmd'",
137 	   ""
138 );
139 
140 /* keep old command name "bootd" for backward compatibility */
141 U_BOOT_CMD(bootd, 1,	1,	do_bootd,
142 	   "boot default, i.e., run 'bootcmd'",
143 	   ""
144 );
145 #endif
146