spl.c 24.7 KB
Newer Older
1
// SPDX-License-Identifier: GPL-2.0+
Aneesh V's avatar
Aneesh V committed
2
3
4
5
6
7
/*
 * (C) Copyright 2010
 * Texas Instruments, <www.ti.com>
 *
 * Aneesh V <aneesh@ti.com>
 */
8

Aneesh V's avatar
Aneesh V committed
9
#include <common.h>
Simon Glass's avatar
Simon Glass committed
10
#include <bloblist.h>
11
#include <binman_sym.h>
12
#include <bootstage.h>
13
#include <dm.h>
14
#include <handoff.h>
15
#include <hang.h>
16
#include <init.h>
17
#include <irq_func.h>
18
#include <log.h>
19
#include <mapmem.h>
20
#include <serial.h>
21
#include <spl.h>
22
#include <system-constants.h>
23
#include <asm/global_data.h>
24
#include <asm-generic/gpio.h>
Aneesh V's avatar
Aneesh V committed
25
#include <asm/u-boot.h>
26
#include <nand.h>
27
#include <fat.h>
28
#include <u-boot/crc.h>
29
30
31
#if CONFIG_IS_ENABLED(BANNER_PRINT)
#include <timestamp.h>
#endif
32
#include <version.h>
33
#include <image.h>
34
#include <malloc.h>
35
#include <mapmem.h>
36
#include <dm/root.h>
37
#include <dm/util.h>
38
#include <linux/compiler.h>
39
#include <fdt_support.h>
40
#include <bootcount.h>
41
#include <wdt.h>
Aneesh V's avatar
Aneesh V committed
42
43

DECLARE_GLOBAL_DATA_PTR;
44
DECLARE_BINMAN_MAGIC_SYM;
Aneesh V's avatar
Aneesh V committed
45

46
47
#ifndef CFG_SYS_UBOOT_START
#define CFG_SYS_UBOOT_START	CONFIG_TEXT_BASE
48
#endif
49

50
u32 *boot_params_ptr = NULL;
Simon Schwarz's avatar
Simon Schwarz committed
51

52
#if CONFIG_IS_ENABLED(BINMAN_UBOOT_SYMBOLS)
53
/* See spl.h for information about this */
54
binman_sym_declare(ulong, u_boot_any, image_pos);
55
56
57
binman_sym_declare(ulong, u_boot_any, size);

#ifdef CONFIG_TPL
58
59
binman_sym_declare(ulong, u_boot_spl_any, image_pos);
binman_sym_declare(ulong, u_boot_spl_any, size);
60
#endif
61

62
#ifdef CONFIG_VPL
63
64
binman_sym_declare(ulong, u_boot_vpl_any, image_pos);
binman_sym_declare(ulong, u_boot_vpl_any, size);
65
66
#endif

67
68
#endif /* BINMAN_UBOOT_SYMBOLS */

69
70
71
/* Define board data structure */
static struct bd_info bdata __attribute__ ((section(".data")));

Marek Vasut's avatar
Marek Vasut committed
72
#if CONFIG_IS_ENABLED(SHOW_BOOT_PROGRESS)
73
74
75
76
/*
 * Board-specific Platform code can reimplement show_boot_progress () if needed
 */
__weak void show_boot_progress(int val) {}
77
#endif
78

79
80
#if defined(CONFIG_SPL_OS_BOOT) || CONFIG_IS_ENABLED(HANDOFF) || \
	defined(CONFIG_SPL_ATF)
81
82
83
84
85
86
87
/* weak, default platform-specific function to initialize dram banks */
__weak int dram_init_banksize(void)
{
	return 0;
}
#endif

88
89
90
91
92
93
94
95
96
97
/*
 * Default function to determine if u-boot or the OS should
 * be started. This implementation always returns 1.
 *
 * Please implement your own board specific funcion to do this.
 *
 * RETURN
 * 0 to not start u-boot
 * positive if u-boot should start
 */
98
#if CONFIG_IS_ENABLED(OS_BOOT)
99
100
__weak int spl_start_uboot(void)
{
101
102
103
	puts(SPL_TPL_PROMPT
	     "Please implement spl_start_uboot() for your board\n");
	puts(SPL_TPL_PROMPT "Direct Linux boot not active!\n");
104
105
	return 1;
}
106
107
108
109
110
111
112
113
114

/*
 * Weak default function for arch specific zImage check. Return zero
 * and fill start and end address if image is recognized.
 */
int __weak bootz_setup(ulong image, ulong *start, ulong *end)
{
	 return 1;
}
115
116
117
118
119

int __weak booti_setup(ulong image, ulong *relocated_addr, ulong *size, bool force_reloc)
{
	 return 1;
}
120
121
#endif

122
123
124
125
126
/* Weak default function for arch/board-specific fixups to the spl_image_info */
void __weak spl_perform_fixups(struct spl_image_info *spl_image)
{
}

127
void spl_fixup_fdt(void *fdt_blob)
128
{
129
#if defined(CONFIG_SPL_OF_LIBFDT)
130
131
	int err;

132
133
134
	if (!fdt_blob)
		return;

135
136
137
138
139
140
141
142
143
	err = fdt_check_header(fdt_blob);
	if (err < 0) {
		printf("fdt_root: %s\n", fdt_strerror(err));
		return;
	}

	/* fixup the memory dt node */
	err = fdt_shrink_to_minimum(fdt_blob, 0);
	if (err == 0) {
144
		printf(SPL_TPL_PROMPT "fdt_shrink_to_minimum err - %d\n", err);
145
146
147
148
149
		return;
	}

	err = arch_fixup_fdt(fdt_blob);
	if (err) {
150
		printf(SPL_TPL_PROMPT "arch_fixup_fdt err - %d\n", err);
151
152
153
154
155
		return;
	}
#endif
}

156
157
ulong spl_get_image_pos(void)
{
158
	if (!CONFIG_IS_ENABLED(BINMAN_UBOOT_SYMBOLS))
159
160
		return BINMAN_SYM_MISSING;

161
162
#ifdef CONFIG_VPL
	if (spl_next_phase() == PHASE_VPL)
163
		return binman_sym(ulong, u_boot_vpl_any, image_pos);
164
165
#endif
	return spl_next_phase() == PHASE_SPL ?
166
		binman_sym(ulong, u_boot_spl_any, image_pos) :
167
168
169
170
171
		binman_sym(ulong, u_boot_any, image_pos);
}

ulong spl_get_image_size(void)
{
172
	if (!CONFIG_IS_ENABLED(BINMAN_UBOOT_SYMBOLS))
173
174
		return BINMAN_SYM_MISSING;

175
176
#ifdef CONFIG_VPL
	if (spl_next_phase() == PHASE_VPL)
177
		return binman_sym(ulong, u_boot_vpl_any, size);
178
179
#endif
	return spl_next_phase() == PHASE_SPL ?
180
		binman_sym(ulong, u_boot_spl_any, size) :
181
182
183
		binman_sym(ulong, u_boot_any, size);
}

184
185
ulong spl_get_image_text_base(void)
{
186
187
188
189
190
#ifdef CONFIG_VPL
	if (spl_next_phase() == PHASE_VPL)
		return CONFIG_VPL_TEXT_BASE;
#endif
	return spl_next_phase() == PHASE_SPL ? CONFIG_SPL_TEXT_BASE :
191
		CONFIG_TEXT_BASE;
192
193
}

194
195
196
197
198
199
200
201
202
203
/*
 * Weak default function for board specific cleanup/preparation before
 * Linux boot. Some boards/platforms might not need it, so just provide
 * an empty stub here.
 */
__weak void spl_board_prepare_for_linux(void)
{
	/* Nothing to do! */
}

204
205
206
207
__weak void spl_board_prepare_for_optee(void *fdt)
{
}

208
209
210
211
212
__weak const char *spl_board_loader_name(u32 boot_device)
{
	return NULL;
}

213
214
215
216
217
218
219
220
#if CONFIG_IS_ENABLED(OPTEE_IMAGE)
__weak void __noreturn jump_to_image_optee(struct spl_image_info *spl_image)
{
	spl_optee_entry(NULL, NULL, spl_image->fdt_addr,
			(void *)spl_image->entry_point);
}
#endif

221
222
223
224
225
__weak void spl_board_prepare_for_boot(void)
{
	/* Nothing to do! */
}

226
__weak struct legacy_img_hdr *spl_get_load_buffer(ssize_t offset, size_t size)
227
{
228
	return map_sysmem(CONFIG_TEXT_BASE + offset, 0);
229
230
}

231
#ifdef CONFIG_SPL_RAW_IMAGE_SUPPORT
232
void spl_set_header_raw_uboot(struct spl_image_info *spl_image)
233
{
234
	ulong u_boot_pos = spl_get_image_pos();
235

236
#if CONFIG_SYS_MONITOR_LEN != 0
237
	spl_image->size = CONFIG_SYS_MONITOR_LEN;
238
239
240
241
#else
	/* Unknown U-Boot size, let's assume it will not be more than 200 KB */
	spl_image->size = 200 * 1024;
#endif
242
243
244
245
246
247
248
249

	/*
	 * Binman error cases: address of the end of the previous region or the
	 * start of the image's entry area (usually 0) if there is no previous
	 * region.
	 */
	if (u_boot_pos && u_boot_pos != BINMAN_SYM_MISSING) {
		/* Binman does not support separated entry addresses */
250
251
252
		spl_image->entry_point = u_boot_pos;
		spl_image->load_addr = u_boot_pos;
	} else {
253
		spl_image->entry_point = CFG_SYS_UBOOT_START;
254
		spl_image->load_addr = CONFIG_TEXT_BASE;
255
	}
256
257
	spl_image->os = IH_OS_U_BOOT;
	spl_image->name = "U-Boot";
258
}
259
#endif
260

261
#if CONFIG_IS_ENABLED(LOAD_FIT_FULL)
Marek Vasut's avatar
Marek Vasut committed
262
263
/* Parse and load full fitImage in SPL */
static int spl_load_fit_image(struct spl_image_info *spl_image,
264
			      const struct legacy_img_hdr *header)
Marek Vasut's avatar
Marek Vasut committed
265
{
266
	struct bootm_headers images;
Marek Vasut's avatar
Marek Vasut committed
267
	const char *fit_uname_config = NULL;
268
	uintptr_t fdt_hack;
Marek Vasut's avatar
Marek Vasut committed
269
270
271
272
273
274
275
276
277
278
279
280
	const char *uname;
	ulong fw_data = 0, dt_data = 0, img_data = 0;
	ulong fw_len = 0, dt_len = 0, img_len = 0;
	int idx, conf_noffset;
	int ret;

#ifdef CONFIG_SPL_FIT_SIGNATURE
	images.verify = 1;
#endif
	ret = fit_image_load(&images, (ulong)header,
			     NULL, &fit_uname_config,
			     IH_ARCH_DEFAULT, IH_TYPE_STANDALONE, -1,
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
			     FIT_LOAD_OPTIONAL, &fw_data, &fw_len);
	if (ret >= 0) {
		printf("DEPRECATED: 'standalone = ' property.");
		printf("Please use either 'firmware =' or 'kernel ='\n");
	} else {
		ret = fit_image_load(&images, (ulong)header, NULL,
				     &fit_uname_config, IH_ARCH_DEFAULT,
				     IH_TYPE_FIRMWARE, -1, FIT_LOAD_OPTIONAL,
				     &fw_data, &fw_len);
	}

	if (ret < 0) {
		ret = fit_image_load(&images, (ulong)header, NULL,
				     &fit_uname_config, IH_ARCH_DEFAULT,
				     IH_TYPE_KERNEL, -1, FIT_LOAD_OPTIONAL,
				     &fw_data, &fw_len);
	}

Marek Vasut's avatar
Marek Vasut committed
299
300
301
302
303
304
	if (ret < 0)
		return ret;

	spl_image->size = fw_len;
	spl_image->entry_point = fw_data;
	spl_image->load_addr = fw_data;
305
306
307
	if (fit_image_get_os(header, ret, &spl_image->os))
		spl_image->os = IH_OS_INVALID;
	spl_image->name = genimg_get_os_name(spl_image->os);
Marek Vasut's avatar
Marek Vasut committed
308

309
	debug(SPL_TPL_PROMPT "payload image: %32s load addr: 0x%lx size: %d\n",
310
	      spl_image->name, spl_image->load_addr, spl_image->size);
Marek Vasut's avatar
Marek Vasut committed
311
312
313
314

#ifdef CONFIG_SPL_FIT_SIGNATURE
	images.verify = 1;
#endif
315
	ret = fit_image_load(&images, (ulong)header, NULL, &fit_uname_config,
Marek Vasut's avatar
Marek Vasut committed
316
317
		       IH_ARCH_DEFAULT, IH_TYPE_FLATDT, -1,
		       FIT_LOAD_OPTIONAL, &dt_data, &dt_len);
318
	if (ret >= 0) {
319
		spl_image->fdt_addr = (void *)dt_data;
Marek Vasut's avatar
Marek Vasut committed
320

321
322
323
324
325
326
327
328
329
		if (spl_image->os == IH_OS_U_BOOT) {
			/* HACK: U-boot expects FDT at a specific address */
			fdt_hack = spl_image->load_addr + spl_image->size;
			fdt_hack = (fdt_hack + 3) & ~3;
			debug("Relocating FDT to %p\n", spl_image->fdt_addr);
			memcpy((void *)fdt_hack, spl_image->fdt_addr, dt_len);
		}
	}

Marek Vasut's avatar
Marek Vasut committed
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
	conf_noffset = fit_conf_get_node((const void *)header,
					 fit_uname_config);
	if (conf_noffset <= 0)
		return 0;

	for (idx = 0;
	     uname = fdt_stringlist_get((const void *)header, conf_noffset,
					FIT_LOADABLE_PROP, idx,
				NULL), uname;
	     idx++)
	{
#ifdef CONFIG_SPL_FIT_SIGNATURE
		images.verify = 1;
#endif
		ret = fit_image_load(&images, (ulong)header,
				     &uname, &fit_uname_config,
				     IH_ARCH_DEFAULT, IH_TYPE_LOADABLE, -1,
				     FIT_LOAD_OPTIONAL_NON_ZERO,
				     &img_data, &img_len);
		if (ret < 0)
			return ret;
	}

	return 0;
}
#endif

357
__weak int spl_parse_board_header(struct spl_image_info *spl_image,
358
				  const struct spl_boot_device *bootdev,
359
360
361
362
363
				  const void *image_header, size_t size)
{
	return -EINVAL;
}

364
__weak int spl_parse_legacy_header(struct spl_image_info *spl_image,
365
				   const struct legacy_img_hdr *header)
366
367
368
369
370
371
{
	/* LEGACY image not supported */
	debug("Legacy boot image support not enabled, proceeding to other boot methods\n");
	return -EINVAL;
}

372
int spl_parse_image_header(struct spl_image_info *spl_image,
373
			   const struct spl_boot_device *bootdev,
374
			   const struct legacy_img_hdr *header)
375
{
376
#if CONFIG_IS_ENABLED(LOAD_FIT_FULL)
Marek Vasut's avatar
Marek Vasut committed
377
378
379
380
381
	int ret = spl_load_fit_image(spl_image, header);

	if (!ret)
		return ret;
#endif
382
	if (image_get_magic(header) == IH_MAGIC) {
383
		int ret;
384

385
386
387
		ret = spl_parse_legacy_header(spl_image, header);
		if (ret)
			return ret;
388
	} else {
389
390
391
392
393
394
395
396
397
398
#ifdef CONFIG_SPL_PANIC_ON_RAW_IMAGE
		/*
		 * CONFIG_SPL_PANIC_ON_RAW_IMAGE is defined when the
		 * code which loads images in SPL cannot guarantee that
		 * absolutely all read errors will be reported.
		 * An example is the LPC32XX MLC NAND driver, which
		 * will consider that a completely unreadable NAND block
		 * is bad, and thus should be skipped silently.
		 */
		panic("** no mkimage signature but raw image not supported");
399
400
#endif

401
#if CONFIG_IS_ENABLED(OS_BOOT)
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
#if defined(CMD_BOOTI)
		ulong start, size;

		if (!booti_setup((ulong)header, &start, &size, 0)) {
			spl_image->name = "Linux";
			spl_image->os = IH_OS_LINUX;
			spl_image->load_addr = start;
			spl_image->entry_point = start;
			spl_image->size = size;
			debug(SPL_TPL_PROMPT
			      "payload Image, load addr: 0x%lx size: %d\n",
			      spl_image->load_addr, spl_image->size);
			return 0;
		}
#elif defined(CMD_BOOTZ)
417
418
419
		ulong start, end;

		if (!bootz_setup((ulong)header, &start, &end)) {
420
421
422
423
424
			spl_image->name = "Linux";
			spl_image->os = IH_OS_LINUX;
			spl_image->load_addr = CONFIG_SYS_LOAD_ADDR;
			spl_image->entry_point = CONFIG_SYS_LOAD_ADDR;
			spl_image->size = end - start;
425
426
			debug(SPL_TPL_PROMPT
			      "payload zImage, load addr: 0x%lx size: %d\n",
427
			      spl_image->load_addr, spl_image->size);
428
429
			return 0;
		}
430
#endif
431
#endif
432

433
		if (!spl_parse_board_header(spl_image, bootdev, (const void *)header, sizeof(*header)))
434
435
			return 0;

436
#ifdef CONFIG_SPL_RAW_IMAGE_SUPPORT
437
		/* Signature not found - assume u-boot.bin */
438
		debug("mkimage signature not found - ih_magic = %x\n",
439
			header->ih_magic);
440
		spl_set_header_raw_uboot(spl_image);
441
442
#else
		/* RAW image not supported, proceed to other boot methods. */
443
		debug("Raw boot image support not enabled, proceeding to other boot methods\n");
444
		return -EINVAL;
445
#endif
446
	}
447

448
	return 0;
449
450
}

451
__weak void __noreturn jump_to_image_no_args(struct spl_image_info *spl_image)
452
{
453
454
	typedef void __noreturn (*image_entry_noargs_t)(void);

455
	image_entry_noargs_t image_entry =
456
		(image_entry_noargs_t)spl_image->entry_point;
457

458
	debug("image entry point: 0x%lx\n", spl_image->entry_point);
459
	image_entry();
460
461
}

462
463
464
465
466
467
468
469
470
471
#if CONFIG_IS_ENABLED(HANDOFF)
/**
 * Set up the SPL hand-off information
 *
 * This is initially empty (zero) but can be written by
 */
static int setup_spl_handoff(void)
{
	struct spl_handoff *ho;

Simon Glass's avatar
Simon Glass committed
472
	ho = bloblist_ensure(BLOBLISTT_U_BOOT_SPL_HANDOFF, sizeof(struct spl_handoff));
473
474
475
476
477
478
	if (!ho)
		return -ENOENT;

	return 0;
}

479
480
481
482
483
__weak int handoff_arch_save(struct spl_handoff *ho)
{
	return 0;
}

484
485
486
static int write_spl_handoff(void)
{
	struct spl_handoff *ho;
487
	int ret;
488

Simon Glass's avatar
Simon Glass committed
489
	ho = bloblist_find(BLOBLISTT_U_BOOT_SPL_HANDOFF, sizeof(struct spl_handoff));
490
491
492
	if (!ho)
		return -ENOENT;
	handoff_save_dram(ho);
493
494
495
	ret = handoff_arch_save(ho);
	if (ret)
		return ret;
496
497
498
499
500
501
502
503
504
505
	debug(SPL_TPL_PROMPT "Wrote SPL handoff\n");

	return 0;
}
#else
static inline int setup_spl_handoff(void) { return 0; }
static inline int write_spl_handoff(void) { return 0; }

#endif /* HANDOFF */

506
507
508
509
/**
 * get_bootstage_id() - Get the bootstage ID to emit
 *
 * @start: true if this is for starting SPL, false for ending it
510
 * Return: bootstage ID to use
511
512
513
514
515
516
517
 */
static enum bootstage_id get_bootstage_id(bool start)
{
	enum u_boot_phase phase = spl_phase();

	if (IS_ENABLED(CONFIG_TPL_BUILD) && phase == PHASE_TPL)
		return start ? BOOTSTAGE_ID_START_TPL : BOOTSTAGE_ID_END_TPL;
518
519
	else if (IS_ENABLED(CONFIG_VPL_BUILD) && phase == PHASE_VPL)
		return start ? BOOTSTAGE_ID_START_VPL : BOOTSTAGE_ID_END_VPL;
520
521
522
523
	else
		return start ? BOOTSTAGE_ID_START_SPL : BOOTSTAGE_ID_END_SPL;
}

Eddie Cai's avatar
Eddie Cai committed
524
static int spl_common_init(bool setup_malloc)
Aneesh V's avatar
Aneesh V committed
525
{
526
527
	int ret;

528
#if CONFIG_VAL(SYS_MALLOC_F_LEN)
Eddie Cai's avatar
Eddie Cai committed
529
	if (setup_malloc) {
530
531
#ifdef CFG_MALLOC_F_ADDR
		gd->malloc_base = CFG_MALLOC_F_ADDR;
532
#endif
533
		gd->malloc_limit = CONFIG_VAL(SYS_MALLOC_F_LEN);
Eddie Cai's avatar
Eddie Cai committed
534
535
		gd->malloc_ptr = 0;
	}
536
#endif
537
	ret = bootstage_init(u_boot_first_phase());
Simon Glass's avatar
Simon Glass committed
538
539
540
541
542
	if (ret) {
		debug("%s: Failed to set up bootstage: ret=%d\n", __func__,
		      ret);
		return ret;
	}
543
544
545
546
547
548
549
550
551
552
553
#ifdef CONFIG_BOOTSTAGE_STASH
	if (!u_boot_first_phase()) {
		const void *stash = map_sysmem(CONFIG_BOOTSTAGE_STASH_ADDR,
					       CONFIG_BOOTSTAGE_STASH_SIZE);

		ret = bootstage_unstash(stash, CONFIG_BOOTSTAGE_STASH_SIZE);
		if (ret)
			debug("%s: Failed to unstash bootstage: ret=%d\n",
			      __func__, ret);
	}
#endif /* CONFIG_BOOTSTAGE_STASH */
554
555
	bootstage_mark_name(get_bootstage_id(true),
			    spl_phase_name(spl_phase()));
556
557
558
559
560
561
562
#if CONFIG_IS_ENABLED(LOG)
	ret = log_init();
	if (ret) {
		debug("%s: Failed to set up logging\n", __func__);
		return ret;
	}
#endif
563
	if (CONFIG_IS_ENABLED(OF_REAL)) {
564
565
566
		ret = fdtdec_setup();
		if (ret) {
			debug("fdtdec_setup() returned error %d\n", ret);
567
			return ret;
568
569
		}
	}
570
	if (CONFIG_IS_ENABLED(DM)) {
571
		bootstage_start(BOOTSTAGE_ID_ACCUM_DM_SPL,
572
				spl_phase() == PHASE_TPL ? "dm tpl" : "dm_spl");
573
		/* With CONFIG_SPL_OF_PLATDATA, bring in all devices */
574
		ret = dm_init_and_scan(!CONFIG_IS_ENABLED(OF_PLATDATA));
575
		bootstage_accum(BOOTSTAGE_ID_ACCUM_DM_SPL);
576
577
		if (ret) {
			debug("dm_init_and_scan() returned error %d\n", ret);
578
			return ret;
579
580
		}
	}
Eddie Cai's avatar
Eddie Cai committed
581
582
583
584

	return 0;
}

585
void spl_set_bd(void)
586
{
587
588
589
590
	/*
	 * NOTE: On some platforms (e.g. x86) bdata may be in flash and not
	 * writeable.
	 */
591
592
	if (!gd->bd)
		gd->bd = &bdata;
593
594
}

Eddie Cai's avatar
Eddie Cai committed
595
596
597
598
int spl_early_init(void)
{
	int ret;

599
600
	debug("%s\n", __func__);

Eddie Cai's avatar
Eddie Cai committed
601
602
603
604
605
606
607
608
609
610
611
	ret = spl_common_init(true);
	if (ret)
		return ret;
	gd->flags |= GD_FLG_SPL_EARLY_INIT;

	return 0;
}

int spl_init(void)
{
	int ret;
612
613
	bool setup_malloc = !(IS_ENABLED(CONFIG_SPL_STACK_R) &&
			IS_ENABLED(CONFIG_SPL_SYS_MALLOC_SIMPLE));
Eddie Cai's avatar
Eddie Cai committed
614

615
616
	debug("%s\n", __func__);

Eddie Cai's avatar
Eddie Cai committed
617
	if (!(gd->flags & GD_FLG_SPL_EARLY_INIT)) {
618
		ret = spl_common_init(setup_malloc);
Eddie Cai's avatar
Eddie Cai committed
619
620
621
		if (ret)
			return ret;
	}
622
	gd->flags |= GD_FLG_SPL_INIT;
623

624
625
626
	return 0;
}

627
628
629
630
631
632
633
634
635
#ifndef BOOT_DEVICE_NONE
#define BOOT_DEVICE_NONE 0xdeadbeef
#endif

__weak void board_boot_order(u32 *spl_boot_list)
{
	spl_boot_list[0] = spl_boot_device();
}

636
637
638
639
640
641
__weak int spl_check_board_image(struct spl_image_info *spl_image,
				 const struct spl_boot_device *bootdev)
{
	return 0;
}

642
643
static int spl_load_image(struct spl_image_info *spl_image,
			  struct spl_image_loader *loader)
644
{
645
	int ret;
646
647
	struct spl_boot_device bootdev;

648
	bootdev.boot_device = loader->boot_device;
649
650
	bootdev.boot_device_name = NULL;

651
652
653
654
655
656
657
658
659
660
661
662
	ret = loader->load_image(spl_image, &bootdev);
#ifdef CONFIG_SPL_LEGACY_IMAGE_CRC_CHECK
	if (!ret && spl_image->dcrc_length) {
		/* check data crc */
		ulong dcrc = crc32_wd(0, (unsigned char *)spl_image->dcrc_data,
				      spl_image->dcrc_length, CHUNKSZ_CRC32);
		if (dcrc != spl_image->dcrc) {
			puts("SPL: Image data CRC check failed!\n");
			ret = -EINVAL;
		}
	}
#endif
663
664
665
	if (!ret)
		ret = spl_check_board_image(spl_image, &bootdev);

666
	return ret;
667
668
669
}

/**
Miquel Raynal's avatar
Miquel Raynal committed
670
 * boot_from_devices() - Try loading a booting U-Boot from a list of devices
671
672
673
674
 *
 * @spl_image: Place to put the image details if successful
 * @spl_boot_list: List of boot devices to try
 * @count: Number of elements in spl_boot_list
675
 * Return: 0 if OK, -ENODEV if there were no boot devices
676
677
 *	if CONFIG_SHOW_ERRORS is enabled, returns -ENXIO if there were
 *	devices but none worked
678
679
680
681
 */
static int boot_from_devices(struct spl_image_info *spl_image,
			     u32 spl_boot_list[], int count)
{
682
683
684
685
	struct spl_image_loader *drv =
		ll_entry_start(struct spl_image_loader, spl_image_loader);
	const int n_ents =
		ll_entry_count(struct spl_image_loader, spl_image_loader);
686
	int ret = -ENODEV;
687
688
689
690
	int i;

	for (i = 0; i < count && spl_boot_list[i] != BOOT_DEVICE_NONE; i++) {
		struct spl_image_loader *loader;
691
692
693
694
		int bootdev = spl_boot_list[i];

		if (CONFIG_IS_ENABLED(SHOW_ERRORS))
			ret = -ENXIO;
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
		for (loader = drv; loader != drv + n_ents; loader++) {
			if (bootdev != loader->boot_device)
				continue;
			if (!CONFIG_IS_ENABLED(SILENT_CONSOLE)) {
				if (loader)
					printf("Trying to boot from %s\n",
					       spl_loader_name(loader));
				else if (CONFIG_IS_ENABLED(SHOW_ERRORS)) {
					printf(SPL_TPL_PROMPT
					       "Unsupported Boot Device %d\n",
					       bootdev);
				} else {
					puts(SPL_TPL_PROMPT
					     "Unsupported Boot Device!\n");
				}
			}
			if (loader &&
				!spl_load_image(spl_image, loader)) {
				spl_image->boot_device = bootdev;
				return 0;
			}
716
		}
717
718
	}

719
	return ret;
720
721
}

722
723
724
725
726
727
728
729
730
731
732
733
734
#if defined(CONFIG_SPL_FRAMEWORK_BOARD_INIT_F)
void board_init_f(ulong dummy)
{
	if (CONFIG_IS_ENABLED(OF_CONTROL)) {
		int ret;

		ret = spl_early_init();
		if (ret) {
			debug("spl_early_init() failed: %d\n", ret);
			hang();
		}
	}

735
	preloader_console_init();
736
737
738
}
#endif

739
740
void board_init_r(gd_t *dummy1, ulong dummy2)
{
741
742
743
744
745
746
747
748
	u32 spl_boot_list[] = {
		BOOT_DEVICE_NONE,
		BOOT_DEVICE_NONE,
		BOOT_DEVICE_NONE,
		BOOT_DEVICE_NONE,
		BOOT_DEVICE_NONE,
	};
	struct spl_image_info spl_image;
Simon Glass's avatar
Simon Glass committed
749
	int ret;
750

751
	debug(">>" SPL_TPL_PROMPT "board_init_r()\n");
752

753
754
	spl_set_bd();

755
756
#if defined(CONFIG_SYS_SPL_MALLOC)
	mem_malloc_init(SYS_SPL_MALLOC_START, CONFIG_SYS_SPL_MALLOC_SIZE);
757
758
759
760
761
762
	gd->flags |= GD_FLG_FULL_MALLOC_INIT;
#endif
	if (!(gd->flags & GD_FLG_SPL_INIT)) {
		if (spl_init())
			hang();
	}
763
#if !defined(CONFIG_PPC) && !defined(CONFIG_ARCH_MX6)
764
765
766
767
768
769
	/*
	 * timer_init() does not exist on PPC systems. The timer is initialized
	 * and enabled (decrementer) in interrupt_init() here.
	 */
	timer_init();
#endif
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
	if (CONFIG_IS_ENABLED(BLOBLIST)) {
		ret = bloblist_init();
		if (ret) {
			debug("%s: Failed to set up bloblist: ret=%d\n",
			      __func__, ret);
			puts(SPL_TPL_PROMPT "Cannot set up bloblist\n");
			hang();
		}
	}
	if (CONFIG_IS_ENABLED(HANDOFF)) {
		int ret;

		ret = setup_spl_handoff();
		if (ret) {
			puts(SPL_TPL_PROMPT "Cannot set up SPL handoff\n");
			hang();
		}
	}
788

789
#if CONFIG_IS_ENABLED(BOARD_INIT)
790
791
792
	spl_board_init();
#endif

793
#if defined(CONFIG_SPL_WATCHDOG) && CONFIG_IS_ENABLED(WDT)
794
795
796
	initr_watchdog();
#endif

797
798
	if (IS_ENABLED(CONFIG_SPL_OS_BOOT) || CONFIG_IS_ENABLED(HANDOFF) ||
	    IS_ENABLED(CONFIG_SPL_ATF))
799
800
		dram_init_banksize();

801
802
	bootcount_inc();

803
804
805
806
807
808
809
810
	/* Dump driver model states to aid analysis */
	if (CONFIG_IS_ENABLED(DM_STATS)) {
		struct dm_stats mem;

		dm_get_mem(&mem);
		dm_dump_mem(&mem);
	}

811
	memset(&spl_image, '\0', sizeof(spl_image));
812
813
814
#ifdef CONFIG_SYS_SPL_ARGS_ADDR
	spl_image.arg = (void *)CONFIG_SYS_SPL_ARGS_ADDR;
#endif
815
	spl_image.boot_device = BOOT_DEVICE_NONE;
816
817
	board_boot_order(spl_boot_list);

818
819
820
821
822
823
824
825
826
	ret = boot_from_devices(&spl_image, spl_boot_list,
				ARRAY_SIZE(spl_boot_list));
	if (ret) {
		if (CONFIG_IS_ENABLED(SHOW_ERRORS) &&
		    CONFIG_IS_ENABLED(LIBCOMMON_SUPPORT))
			printf(SPL_TPL_PROMPT "failed to boot from all boot devices (err=%d)\n",
			       ret);
		else
			puts(SPL_TPL_PROMPT "failed to boot from all boot devices\n");
827
		hang();
828
	}
829

830
	spl_perform_fixups(&spl_image);
831
832
833
834
835
836
	if (CONFIG_IS_ENABLED(HANDOFF)) {
		ret = write_spl_handoff();
		if (ret)
			printf(SPL_TPL_PROMPT
			       "SPL hand-off write failed (err=%d)\n", ret);
	}
Simon Glass's avatar
Simon Glass committed
837
838
839
840
841
842
	if (CONFIG_IS_ENABLED(BLOBLIST)) {
		ret = bloblist_finish();
		if (ret)
			printf("Warning: Failed to finish bloblist (ret=%d)\n",
			       ret);
	}
843

Simon Schwarz's avatar
Simon Schwarz committed
844
	switch (spl_image.os) {
845
	case IH_OS_U_BOOT:
846
		debug("Jumping to %s...\n", spl_phase_name(spl_next_phase()));
847
		break;
848
849
850
#if CONFIG_IS_ENABLED(ATF)
	case IH_OS_ARM_TRUSTED_FIRMWARE:
		debug("Jumping to U-Boot via ARM Trusted Firmware\n");
851
		spl_fixup_fdt(spl_image.fdt_addr);
852
853
854
		spl_invoke_atf(&spl_image);
		break;
#endif
855
#if CONFIG_IS_ENABLED(OPTEE_IMAGE)
856
857
	case IH_OS_TEE:
		debug("Jumping to U-Boot via OP-TEE\n");
858
		spl_board_prepare_for_optee(spl_image.fdt_addr);
859
		jump_to_image_optee(&spl_image);
860
861
		break;
#endif
862
863
864
865
866
867
#if CONFIG_IS_ENABLED(OPENSBI)
	case IH_OS_OPENSBI:
		debug("Jumping to U-Boot via RISC-V OpenSBI\n");
		spl_invoke_opensbi(&spl_image);
		break;
#endif
868
#if CONFIG_IS_ENABLED(OS_BOOT)
869
870
	case IH_OS_LINUX:
		debug("Jumping to Linux\n");
871
872
873
#if defined(CONFIG_SYS_SPL_ARGS_ADDR)
		spl_fixup_fdt((void *)CONFIG_SYS_SPL_ARGS_ADDR);
#endif
874
		spl_board_prepare_for_linux();
875
		jump_to_image_linux(&spl_image);
876
#endif
877
	default:
878
		debug("Unsupported OS image.. Jumping nevertheless..\n");
879
	}
880
#if CONFIG_VAL(SYS_MALLOC_F_LEN) && !defined(CONFIG_SYS_SPL_MALLOC_SIZE)
881
	debug("SPL malloc() used 0x%lx bytes (%ld KB)\n", gd->malloc_ptr,
882
883
	      gd->malloc_ptr / 1024);
#endif
884
	bootstage_mark_name(get_bootstage_id(false), "end phase");
Simon Glass's avatar
Simon Glass committed
885
886
887
888
889
890
#ifdef CONFIG_BOOTSTAGE_STASH
	ret = bootstage_stash((void *)CONFIG_BOOTSTAGE_STASH_ADDR,
			      CONFIG_BOOTSTAGE_STASH_SIZE);
	if (ret)
		debug("Failed to stash bootstage: err=%d\n", ret);
#endif
891

892
	spl_board_prepare_for_boot();
893
	jump_to_image_no_args(&spl_image);
Aneesh V's avatar
Aneesh V committed
894
895
}

896
897
898
899
/*
 * This requires UART clocks to be enabled.  In order for this to work the
 * caller must ensure that the gd pointer is valid.
 */
Aneesh V's avatar
Aneesh V committed
900
901
void preloader_console_init(void)
{
902
#ifdef CONFIG_SPL_SERIAL
Aneesh V's avatar
Aneesh V committed
903
904
905
906
	gd->baudrate = CONFIG_BAUDRATE;

	serial_init();		/* serial communications setup */

907
908
	gd->have_console = 1;

909
#if CONFIG_IS_ENABLED(BANNER_PRINT)
910
911
	puts("\nU-Boot " SPL_TPL_NAME " " PLAIN_VERSION " (" U_BOOT_DATE " - "
	     U_BOOT_TIME " " U_BOOT_TZ ")\n");
912
#endif
913
914
915
#ifdef CONFIG_SPL_DISPLAY_PRINT
	spl_display_print();
#endif
916
#endif
917
}
918

919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
/**
 * This function is called before the stack is changed from initial stack to
 * relocated stack. It tries to dump the stack size used
 */
__weak void spl_relocate_stack_check(void)
{
#if CONFIG_IS_ENABLED(SYS_REPORT_STACK_F_USAGE)
	ulong init_sp = gd->start_addr_sp;
	ulong stack_bottom = init_sp - CONFIG_VAL(SIZE_LIMIT_PROVIDE_STACK);
	u8 *ptr = (u8 *)stack_bottom;
	ulong i;

	for (i = 0; i < CONFIG_VAL(SIZE_LIMIT_PROVIDE_STACK); i++) {
		if (*ptr != CONFIG_VAL(SYS_STACK_F_CHECK_BYTE))
			break;
		ptr++;
	}
	printf("SPL initial stack usage: %lu bytes\n",
	       CONFIG_VAL(SIZE_LIMIT_PROVIDE_STACK) - i);
#endif
}

941
942
943
944
945
946
947
948
/**
 * spl_relocate_stack_gd() - Relocate stack ready for board_init_r() execution
 *
 * Sometimes board_init_f() runs with a stack in SRAM but we want to use SDRAM
 * for the main board_init_r() execution. This is typically because we need
 * more stack space for things like the MMC sub-system.
 *
 * This function calculates the stack position, copies the global_data into
949
950
951
952
953
954
955
 * place, sets the new gd (except for ARM, for which setting GD within a C
 * function may not always work) and returns the new stack position. The
 * caller is responsible for setting up the sp register and, in the case
 * of ARM, setting up gd.
 *
 * All of this is done using the same layout and alignments as done in
 * board_init_f_init_reserve() / board_init_f_alloc_reserve().
956
 *
957
 * Return: new stack location, or 0 to use the same stack
958
959
960
961
962
 */
ulong spl_relocate_stack_gd(void)
{
#ifdef CONFIG_SPL_STACK_R
	gd_t *new_gd;
963
	ulong ptr = CONFIG_SPL_STACK_R_ADDR;
964

965
966
967
	if (CONFIG_IS_ENABLED(SYS_REPORT_STACK_F_USAGE))
		spl_relocate_stack_check();

968
#if defined(CONFIG_SPL_SYS_MALLOC_SIMPLE) && CONFIG_VAL(SYS_MALLOC_F_LEN)
969
	if (CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN) {
970
971
		debug("SPL malloc() before relocation used 0x%lx bytes (%ld KB)\n",
		      gd->malloc_ptr, gd->malloc_ptr / 1024);
972
973
974
975
976
977
		ptr -= CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN;
		gd->malloc_base = ptr;
		gd->malloc_limit = CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN;
		gd->malloc_ptr = 0;
	}
#endif
978
979
980
981
	/* Get stack position: use 8-byte alignment for ABI compliance */
	ptr = CONFIG_SPL_STACK_R_ADDR - roundup(sizeof(gd_t),16);
	new_gd = (gd_t *)ptr;
	memcpy(new_gd, (void *)gd, sizeof(gd_t));
982
983
984
#if CONFIG_IS_ENABLED(DM)
	dm_fixup_for_gd_move(new_gd);
#endif
985
#if !defined(CONFIG_ARM) && !defined(CONFIG_RISCV)
986
987
	gd = new_gd;
#endif
988
989
990
991
992
	return ptr;
#else
	return 0;
#endif
}
993

994
995
996
#if defined(CONFIG_BOOTCOUNT_LIMIT) && \
	((!defined(CONFIG_TPL_BUILD) && !defined(CONFIG_SPL_BOOTCOUNT_LIMIT)) || \
	 (defined(CONFIG_TPL_BUILD) && !defined(CONFIG_TPL_BOOTCOUNT_LIMIT)))
997
998
999
1000
void bootcount_store(ulong a)
{
}

For faster browsing, not all history is shown. View entire blame