]> Git Repo - J-u-boot.git/blame - arch/x86/lib/bootm.c
bootm: Adjust arguments of boot_os_fn
[J-u-boot.git] / arch / x86 / lib / bootm.c
CommitLineData
83d290c5 1// SPDX-License-Identifier: GPL-2.0+
2262cfee
WD
2/*
3 * (C) Copyright 2002
4 * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
5 * Marius Groeger <[email protected]>
6 *
7 * Copyright (C) 2001 Erik Mouw ([email protected])
2262cfee
WD
8 */
9
10#include <common.h>
a48336e5 11#include <bootm.h>
52f24238 12#include <bootstage.h>
2262cfee 13#include <command.h>
5a2a1d80 14#include <efi.h>
db41d65a 15#include <hang.h>
f7ae49fc 16#include <log.h>
401d1c4f 17#include <asm/global_data.h>
7025b054
SR
18#include <dm/device.h>
19#include <dm/root.h>
76539383 20#include <errno.h>
0d0ba59c 21#include <fdt_support.h>
2262cfee 22#include <image.h>
a31e091a 23#include <u-boot/zlib.h>
69370d14 24#include <asm/bootparam.h>
61643ae6 25#include <asm/cpu.h>
2262cfee
WD
26#include <asm/byteorder.h>
27#include <asm/zimage.h>
0d0ba59c
SG
28#ifdef CONFIG_SYS_COREBOOT
29#include <asm/arch/timestamp.h>
30#endif
2262cfee 31
8b097916
SG
32DECLARE_GLOBAL_DATA_PTR;
33
69370d14
GB
34#define COMMAND_LINE_OFFSET 0x9000
35
0d0ba59c
SG
36void bootm_announce_and_cleanup(void)
37{
38 printf("\nStarting kernel ...\n\n");
39
40#ifdef CONFIG_SYS_COREBOOT
f9f06e62 41 timestamp_add_now(TS_START_KERNEL);
0d0ba59c
SG
42#endif
43 bootstage_mark_name(BOOTSTAGE_ID_BOOTM_HANDOFF, "start_kernel");
b8bffe66 44#if IS_ENABLED(CONFIG_BOOTSTAGE_REPORT)
0d0ba59c 45 bootstage_report();
cd7c596e 46#endif
7025b054
SR
47
48 /*
49 * Call remove function of all devices with a removal flag set.
50 * This may be useful for last-stage operations, like cancelling
51 * of DMA operation or releasing device internal buffers.
52 */
53 dm_remove_devices_flags(DM_REMOVE_ACTIVE_ALL);
0d0ba59c 54}
8bde7f77 55
0d0ba59c
SG
56#if defined(CONFIG_OF_LIBFDT) && !defined(CONFIG_OF_NO_KERNEL)
57int arch_fixup_memory_node(void *blob)
58{
b75d8dc5 59 struct bd_info *bd = gd->bd;
0d0ba59c
SG
60 int bank;
61 u64 start[CONFIG_NR_DRAM_BANKS];
62 u64 size[CONFIG_NR_DRAM_BANKS];
63
64 for (bank = 0; bank < CONFIG_NR_DRAM_BANKS; bank++) {
65 start[bank] = bd->bi_dram[bank].start;
66 size[bank] = bd->bi_dram[bank].size;
67 }
68
69 return fdt_fixup_memory_banks(blob, start, size, CONFIG_NR_DRAM_BANKS);
70}
71#endif
49c3a861 72
0d0ba59c 73/* Subcommand: PREP */
d9d7c20b 74static int boot_prep_linux(struct bootm_headers *images)
0d0ba59c
SG
75{
76 char *cmd_line_dest = NULL;
f3543e69 77 struct legacy_img_hdr *hdr;
0d0ba59c
SG
78 int is_zimage = 0;
79 void *data = NULL;
80 size_t len;
81 int ret;
82
210af549 83 if (CONFIG_IS_ENABLED(OF_LIBFDT) && IS_ENABLED(CONFIG_LMB) && images->ft_len) {
0d0ba59c
SG
84 debug("using: FDT\n");
85 if (image_setup_linux(images)) {
86 puts("FDT creation failed! hanging...");
87 hang();
88 }
89 }
65168910 90
d5934ad7
MB
91 if (images->legacy_hdr_valid) {
92 hdr = images->legacy_hdr_os;
83088afb 93 if (image_check_type(hdr, IH_TYPE_MULTI)) {
0d0ba59c
SG
94 ulong os_data, os_len;
95
d5934ad7 96 /* if multi-part image, we need to get first subimage */
83088afb 97 image_multi_getimg(hdr, 0, &os_data, &os_len);
0d0ba59c
SG
98 data = (void *)os_data;
99 len = os_len;
d5934ad7
MB
100 } else {
101 /* otherwise get image data */
0d0ba59c
SG
102 data = (void *)image_get_data(hdr);
103 len = image_get_data_size(hdr);
d5934ad7 104 }
0d0ba59c 105 is_zimage = 1;
d5934ad7 106#if defined(CONFIG_FIT)
25475249 107 } else if (images->fit_uname_os && is_zimage) {
83088afb 108 ret = fit_image_get_data(images->fit_hdr_os,
0d0ba59c
SG
109 images->fit_noffset_os,
110 (const void **)&data, &len);
cd7c596e 111 if (ret) {
83088afb 112 puts("Can't get image data/size!\n");
cd7c596e
MB
113 goto error;
114 }
0d0ba59c 115 is_zimage = 1;
d5934ad7 116#endif
e644670b
WD
117 }
118
0d0ba59c 119 if (is_zimage) {
76539383 120 ulong load_address;
0d0ba59c 121 char *base_ptr;
2262cfee 122
0d0ba59c 123 base_ptr = (char *)load_zimage(data, len, &load_address);
c74e3295
HS
124 if (!base_ptr) {
125 puts("## Kernel loading failed ...\n");
126 goto error;
127 }
76539383 128 images->os.load = load_address;
0d0ba59c
SG
129 cmd_line_dest = base_ptr + COMMAND_LINE_OFFSET;
130 images->ep = (ulong)base_ptr;
131 } else if (images->ep) {
132 cmd_line_dest = (void *)images->ep + COMMAND_LINE_OFFSET;
133 } else {
2c363cb0 134 printf("## Kernel loading failed (missing x86 kernel setup) ...\n");
cd7c596e 135 goto error;
69370d14 136 }
8bde7f77 137
0d0ba59c
SG
138 printf("Setup at %#08lx\n", images->ep);
139 ret = setup_zimage((void *)images->ep, cmd_line_dest,
69370d14 140 0, images->rd_start,
4f96023a 141 images->rd_end - images->rd_start, 0);
0d0ba59c
SG
142
143 if (ret) {
69370d14 144 printf("## Setting up boot parameters failed ...\n");
0d0ba59c 145 return 1;
2262cfee 146 }
8bde7f77 147
0d0ba59c 148 return 0;
2262cfee 149
cd7c596e 150error:
40d7e99d 151 return 1;
8bde7f77 152}
0d0ba59c 153
37c9f9cc 154int boot_linux_kernel(ulong setup_base, ulong entry, bool image_64bit)
76539383
SG
155{
156 bootm_announce_and_cleanup();
157
158#ifdef CONFIG_SYS_COREBOOT
159 timestamp_add_now(TS_U_BOOT_START_KERNEL);
160#endif
5a2a1d80
SG
161
162 /*
163 * Exit EFI boot services just before jumping, after all console
164 * output, since the console won't be available afterwards.
165 */
166 if (IS_ENABLED(CONFIG_EFI_APP)) {
167 int ret;
168
169 ret = efi_store_memory_map(efi_get_priv());
170 if (ret)
171 return ret;
172 printf("Exiting EFI boot services\n");
173 ret = efi_call_exit_boot_services();
174 if (ret)
175 return ret;
176 }
177
76539383 178 if (image_64bit) {
61643ae6
SG
179 if (!cpu_has_64bit()) {
180 puts("Cannot boot 64-bit kernel on 32-bit machine\n");
181 return -EFAULT;
182 }
37c9f9cc
SG
183 /*
184 * At present 64-bit U-Boot only supports booting a 64-bit
23b89d4d 185 * kernel.
37c9f9cc
SG
186 *
187 * TODO([email protected]): Support booting 32-bit kernels from
188 * 64-bit U-Boot
23b89d4d 189 */
37c9f9cc
SG
190 if (CONFIG_IS_ENABLED(X86_64)) {
191 typedef void (*h_func)(ulong zero, ulong setup);
192 h_func func;
193
194 /* jump to Linux with rdi=0, rsi=setup_base */
195 func = (h_func)entry;
196 func(0, setup_base);
197 } else {
198 return cpu_jump_to_64bit(setup_base, entry);
199 }
76539383
SG
200 } else {
201 /*
202 * Set %ebx, %ebp, and %edi to 0, %esi to point to the
203 * boot_params structure, and then jump to the kernel. We
204 * assume that %cs is 0x10, 4GB flat, and read/execute, and
205 * the data segments are 0x18, 4GB flat, and read/write.
a187559e 206 * U-Boot is setting them up that way for itself in
76539383 207 * arch/i386/cpu/cpu.c.
e49cceac 208 *
6e7ad4a4
SG
209 * Note: this is incomplete for EFI kernels!
210 *
211 * This can boot a kernel while running as an EFI application,
212 * but if the kernel requires EFI support then that support needs
213 * to be enabled first (see EFI_LOADER). Also the EFI information
214 * must enabled with setup_efi_info(). See setup_zimage() for
215 * how this is done with the stub.
76539383
SG
216 */
217 __asm__ __volatile__ (
218 "movl $0, %%ebp\n"
219 "cli\n"
220 "jmp *%[kernel_entry]\n"
37c9f9cc 221 :: [kernel_entry]"a"(entry),
76539383
SG
222 [boot_params] "S"(setup_base),
223 "b"(0), "D"(0)
224 );
225 }
226
227 /* We can't get to here */
228 return -EFAULT;
229}
230
0d0ba59c 231/* Subcommand: GO */
d9d7c20b 232static int boot_jump_linux(struct bootm_headers *images)
0d0ba59c
SG
233{
234 debug("## Transferring control to Linux (at address %08lx, kernel %08lx) ...\n",
235 images->ep, images->os.load);
236
61643ae6
SG
237 return boot_linux_kernel(images->ep, images->os.load,
238 images->os.arch == IH_ARCH_X86_64);
0d0ba59c
SG
239}
240
a48336e5 241int do_bootm_linux(int flag, struct bootm_info *bmi)
0d0ba59c 242{
a48336e5
SG
243 struct bootm_headers *images = bmi->images;
244
0d0ba59c
SG
245 /* No need for those on x86 */
246 if (flag & BOOTM_STATE_OS_BD_T || flag & BOOTM_STATE_OS_CMDLINE)
247 return -1;
248
249 if (flag & BOOTM_STATE_OS_PREP)
250 return boot_prep_linux(images);
251
76539383
SG
252 if (flag & BOOTM_STATE_OS_GO)
253 return boot_jump_linux(images);
0d0ba59c
SG
254
255 return boot_jump_linux(images);
256}
a69753f3
MV
257
258static ulong get_sp(void)
259{
260 ulong ret;
261
262#if CONFIG_IS_ENABLED(X86_64)
67884002 263 asm("mov %%rsp, %0" : "=r"(ret) : );
a69753f3
MV
264#else
265 asm("mov %%esp, %0" : "=r"(ret) : );
266#endif
267
268 return ret;
269}
270
271void arch_lmb_reserve(struct lmb *lmb)
272{
273 arch_lmb_reserve_generic(lmb, get_sp(), gd->ram_top, 4096);
274}
This page took 0.608164 seconds and 4 git commands to generate.