Loading...
   1
   2
   3
   4
   5
   6
   7
   8
   9
  10
  11
  12
  13
  14
  15
  16
  17
  18
  19
  20
  21
  22
  23
  24
  25
  26
  27
  28
  29
  30
  31
  32
  33
  34
  35
  36
  37
  38
  39
  40
  41
  42
  43
  44
  45
  46
  47
  48
  49
  50
  51
  52
  53
  54
  55
  56
  57
  58
  59
  60
  61
  62
  63
  64
  65
  66
  67
  68
  69
  70
  71
  72
  73
  74
  75
  76
  77
  78
  79
  80
  81
  82
  83
  84
  85
  86
  87
  88
  89
  90
  91
  92
  93
  94
  95
  96
  97
  98
  99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
 112
 113
 114
 115
 116
 117
 118
 119
 120
 121
 122
 123
 124
 125
 126
 127
 128
 129
 130
 131
 132
 133
 134
 135
 136
 137
 138
 139
 140
 141
 142
 143
 144
 145
 146
 147
 148
 149
 150
 151
 152
 153
 154
 155
 156
 157
 158
 159
 160
 161
 162
 163
 164
 165
 166
 167
 168
 169
 170
 171
 172
 173
 174
 175
 176
 177
 178
 179
 180
 181
 182
 183
 184
 185
 186
 187
 188
 189
 190
 191
 192
 193
 194
 195
 196
 197
 198
 199
 200
 201
 202
 203
 204
 205
 206
 207
 208
 209
 210
 211
 212
 213
 214
 215
 216
 217
 218
 219
 220
 221
 222
 223
 224
 225
 226
 227
 228
 229
 230
 231
 232
 233
 234
 235
 236
 237
 238
 239
 240
 241
 242
 243
 244
 245
 246
 247
 248
 249
 250
 251
 252
 253
 254
 255
 256
 257
 258
 259
 260
 261
 262
 263
 264
 265
 266
 267
 268
 269
 270
 271
 272
 273
 274
 275
 276
 277
 278
 279
 280
 281
 282
 283
 284
 285
 286
 287
 288
 289
 290
 291
 292
 293
 294
 295
 296
 297
 298
 299
 300
 301
 302
 303
 304
 305
 306
 307
 308
 309
 310
 311
 312
 313
 314
 315
 316
 317
 318
 319
 320
 321
 322
 323
 324
 325
 326
 327
 328
 329
 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
 357
 358
 359
 360
 361
 362
 363
 364
 365
 366
 367
 368
 369
 370
 371
 372
 373
 374
 375
 376
 377
 378
 379
 380
 381
 382
 383
 384
 385
 386
 387
 388
 389
 390
 391
 392
 393
 394
 395
 396
 397
 398
 399
 400
 401
 402
 403
 404
 405
 406
 407
 408
 409
 410
 411
 412
 413
 414
 415
 416
 417
 418
 419
 420
 421
 422
 423
 424
 425
 426
 427
 428
 429
 430
 431
 432
 433
 434
 435
 436
 437
 438
 439
 440
 441
 442
 443
 444
 445
 446
 447
 448
 449
 450
 451
 452
 453
 454
 455
 456
 457
 458
 459
 460
 461
 462
 463
 464
 465
 466
 467
 468
 469
 470
 471
 472
 473
 474
 475
 476
 477
 478
 479
 480
 481
 482
 483
 484
 485
 486
 487
 488
 489
 490
 491
 492
 493
 494
 495
 496
 497
 498
 499
 500
 501
 502
 503
 504
 505
 506
 507
 508
 509
 510
 511
 512
 513
 514
 515
 516
 517
 518
 519
 520
 521
 522
 523
 524
 525
 526
 527
 528
 529
 530
 531
 532
 533
 534
 535
 536
 537
 538
 539
 540
 541
 542
 543
 544
 545
 546
 547
 548
 549
 550
 551
 552
 553
 554
 555
 556
 557
 558
 559
 560
 561
 562
 563
 564
 565
 566
 567
 568
 569
 570
 571
 572
 573
 574
 575
 576
 577
 578
 579
 580
 581
 582
 583
 584
 585
 586
 587
 588
 589
 590
 591
 592
 593
 594
 595
 596
 597
 598
 599
 600
 601
 602
 603
 604
 605
 606
 607
 608
 609
 610
 611
 612
 613
 614
 615
 616
 617
 618
 619
 620
 621
 622
 623
 624
 625
 626
 627
 628
 629
 630
 631
 632
 633
 634
 635
 636
 637
 638
 639
 640
 641
 642
 643
 644
 645
 646
 647
 648
 649
 650
 651
 652
 653
 654
 655
 656
 657
 658
 659
 660
 661
 662
 663
 664
 665
 666
 667
 668
 669
 670
 671
 672
 673
 674
 675
 676
 677
 678
 679
 680
 681
 682
 683
 684
 685
 686
 687
 688
 689
 690
 691
 692
 693
 694
 695
 696
 697
 698
 699
 700
 701
 702
 703
 704
 705
 706
 707
 708
 709
 710
 711
 712
 713
 714
 715
 716
 717
 718
 719
 720
 721
 722
 723
 724
 725
 726
 727
 728
 729
 730
 731
 732
 733
 734
 735
 736
 737
 738
 739
 740
 741
 742
 743
 744
 745
 746
 747
 748
 749
 750
 751
 752
 753
 754
 755
 756
 757
 758
 759
 760
 761
 762
 763
 764
 765
 766
 767
 768
 769
 770
 771
 772
 773
 774
 775
 776
 777
 778
 779
 780
 781
 782
 783
 784
 785
 786
 787
 788
 789
 790
 791
 792
 793
 794
 795
 796
 797
 798
 799
 800
 801
 802
 803
 804
 805
 806
 807
 808
 809
 810
 811
 812
 813
 814
 815
 816
 817
 818
 819
 820
 821
 822
 823
 824
 825
 826
 827
 828
 829
 830
 831
 832
 833
 834
 835
 836
 837
 838
 839
 840
 841
 842
 843
 844
 845
 846
 847
 848
 849
 850
 851
 852
 853
 854
 855
 856
 857
 858
 859
 860
 861
 862
 863
 864
 865
 866
 867
 868
 869
 870
 871
 872
 873
 874
 875
 876
 877
 878
 879
 880
 881
 882
 883
 884
 885
 886
 887
 888
 889
 890
 891
 892
 893
 894
 895
 896
 897
 898
 899
 900
 901
 902
 903
 904
 905
 906
 907
 908
 909
 910
 911
 912
 913
 914
 915
 916
 917
 918
 919
 920
 921
 922
 923
 924
 925
 926
 927
 928
 929
 930
 931
 932
 933
 934
 935
 936
 937
 938
 939
 940
 941
 942
 943
 944
 945
 946
 947
 948
 949
 950
 951
 952
 953
 954
 955
 956
 957
 958
 959
 960
 961
 962
 963
 964
 965
 966
 967
 968
 969
 970
 971
 972
 973
 974
 975
 976
 977
 978
 979
 980
 981
 982
 983
 984
 985
 986
 987
 988
 989
 990
 991
 992
 993
 994
 995
 996
 997
 998
 999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
/* SPDX-License-Identifier: GPL-2.0+ */
/*
 * (C) Copyright 2012
 * Texas Instruments, <www.ti.com>
 */
#ifndef	_SPL_H_
#define	_SPL_H_

#include <binman_sym.h>
#include <linker_lists.h>

/* Platform-specific defines */
#include <linux/compiler.h>
#include <asm/global_data.h>
#include <asm/spl.h>
#include <handoff.h>
#include <mmc.h>

struct blk_desc;
struct legacy_img_hdr;

/* Value in r0 indicates we booted from U-Boot */
#define UBOOT_NOT_LOADED_FROM_SPL	0x13578642

/* Boot type */
#define MMCSD_MODE_UNDEFINED	0
#define MMCSD_MODE_RAW		1
#define MMCSD_MODE_FS		2
#define MMCSD_MODE_EMMCBOOT	3

struct blk_desc;
struct legacy_img_hdr;
struct spl_boot_device;
enum boot_device;

/*
 * u_boot_first_phase() - check if this is the first U-Boot phase
 *
 * U-Boot has up to three phases: TPL, SPL and U-Boot proper. Depending on the
 * build flags we can determine whether the current build is for the first
 * phase of U-Boot or not. If there is no SPL, then this is U-Boot proper. If
 * there is SPL but no TPL, the the first phase is SPL. If there is TPL, then
 * it is the first phase.
 *
 * @returns true if this is the first phase of U-Boot
 *
 */
static inline bool u_boot_first_phase(void)
{
	if (IS_ENABLED(CONFIG_TPL)) {
		if (IS_ENABLED(CONFIG_TPL_BUILD))
			return true;
	} else if (IS_ENABLED(CONFIG_SPL)) {
		if (IS_ENABLED(CONFIG_SPL_BUILD))
			return true;
	} else {
		return true;
	}

	return false;
}

enum u_boot_phase {
	PHASE_NONE,	/* Invalid phase, signifying before U-Boot */
	PHASE_TPL,	/* Running in TPL */
	PHASE_VPL,	/* Running in VPL */
	PHASE_SPL,	/* Running in SPL */
	PHASE_BOARD_F,	/* Running in U-Boot before relocation */
	PHASE_BOARD_R,	/* Running in U-Boot after relocation */

	PHASE_COUNT,
};

/**
 * spl_phase() - Find out the phase of U-Boot
 *
 * This can be used to avoid #ifdef logic and use if() instead.
 *
 * For example, to include code only in TPL, you might do:
 *
 *    #ifdef CONFIG_TPL_BUILD
 *    ...
 *    #endif
 *
 * but with this you can use:
 *
 *    if (spl_phase() == PHASE_TPL) {
 *       ...
 *    }
 *
 * To include code only in SPL, you might do:
 *
 *    #if defined(CONFIG_SPL_BUILD) && !defined(CONFIG_TPL_BUILD)
 *    ...
 *    #endif
 *
 * but with this you can use:
 *
 *    if (spl_phase() == PHASE_SPL) {
 *       ...
 *    }
 *
 * To include code only in U-Boot proper, you might do:
 *
 *    #ifndef CONFIG_SPL_BUILD
 *    ...
 *    #endif
 *
 * but with this you can use:
 *
 *    if (spl_phase() == PHASE_BOARD_F) {
 *       ...
 *    }
 *
 * Return: U-Boot phase
 */
static inline enum u_boot_phase spl_phase(void)
{
#ifdef CONFIG_TPL_BUILD
	return PHASE_TPL;
#elif defined(CONFIG_VPL_BUILD)
	return PHASE_VPL;
#elif defined(CONFIG_SPL_BUILD)
	return PHASE_SPL;
#else
	DECLARE_GLOBAL_DATA_PTR;

	if (!(gd->flags & GD_FLG_RELOC))
		return PHASE_BOARD_F;
	else
		return PHASE_BOARD_R;
#endif
}

/* returns true if in U-Boot proper, false if in SPL */
static inline bool spl_in_proper(void)
{
#ifdef CONFIG_SPL_BUILD
	return false;
#endif

	return true;
}

/**
 * spl_prev_phase() - Figure out the previous U-Boot phase
 *
 * Return: the previous phase from this one, e.g. if called in SPL this returns
 *	PHASE_TPL, if TPL is enabled
 */
static inline enum u_boot_phase spl_prev_phase(void)
{
#ifdef CONFIG_TPL_BUILD
	return PHASE_NONE;
#elif defined(CONFIG_VPL_BUILD)
	return PHASE_TPL;	/* VPL requires TPL */
#elif defined(CONFIG_SPL_BUILD)
	return IS_ENABLED(CONFIG_VPL) ? PHASE_VPL :
		IS_ENABLED(CONFIG_TPL) ? PHASE_TPL :
		PHASE_NONE;
#else
	return IS_ENABLED(CONFIG_SPL) ? PHASE_SPL :
		PHASE_NONE;
#endif
}

/**
 * spl_next_phase() - Figure out the next U-Boot phase
 *
 * Return: the next phase from this one, e.g. if called in TPL this returns
 *	PHASE_SPL
 */
static inline enum u_boot_phase spl_next_phase(void)
{
#ifdef CONFIG_TPL_BUILD
	return IS_ENABLED(CONFIG_VPL) ? PHASE_VPL : PHASE_SPL;
#elif defined(CONFIG_VPL_BUILD)
	return PHASE_SPL;
#else
	return PHASE_BOARD_F;
#endif
}

/**
 * spl_phase_name() - Get the name of the current phase
 *
 * Return: phase name
 */
static inline const char *spl_phase_name(enum u_boot_phase phase)
{
	switch (phase) {
	case PHASE_TPL:
		return "TPL";
	case PHASE_VPL:
		return "VPL";
	case PHASE_SPL:
		return "SPL";
	case PHASE_BOARD_F:
	case PHASE_BOARD_R:
		return "U-Boot";
	default:
		return "phase?";
	}
}

/**
 * spl_phase_prefix() - Get the prefix  of the current phase
 *
 * @phase: Phase to look up
 * Return: phase prefix ("spl", "tpl", etc.)
 */
static inline const char *spl_phase_prefix(enum u_boot_phase phase)
{
	switch (phase) {
	case PHASE_TPL:
		return "tpl";
	case PHASE_VPL:
		return "vpl";
	case PHASE_SPL:
		return "spl";
	case PHASE_BOARD_F:
	case PHASE_BOARD_R:
		return "";
	default:
		return "phase?";
	}
}

/* A string name for SPL or TPL */
#ifdef CONFIG_SPL_BUILD
# ifdef CONFIG_TPL_BUILD
#  define SPL_TPL_NAME	"TPL"
# elif defined(CONFIG_VPL_BUILD)
#  define SPL_TPL_NAME	"VPL"
# else
#  define SPL_TPL_NAME	"SPL"
# endif
# define SPL_TPL_PROMPT	SPL_TPL_NAME ": "
#else
# define SPL_TPL_NAME	""
# define SPL_TPL_PROMPT	""
#endif

/**
 * enum spl_sandbox_flags - flags for sandbox's use of spl_image_info->flags
 *
 * @SPL_SANDBOXF_ARG_IS_FNAME: arg is the filename to jump to (default)
 * @SPL_SANDBOXF_ARG_IS_BUF: arg is the containing image to jump to, @offset is
 *	the start offset within the image, @size is the size of the image
 */
enum spl_sandbox_flags {
	SPL_SANDBOXF_ARG_IS_FNAME = 0,
	SPL_SANDBOXF_ARG_IS_BUF,
};

struct spl_image_info {
	const char *name;
	u8 os;
	uintptr_t load_addr;
	uintptr_t entry_point;
#if CONFIG_IS_ENABLED(LOAD_FIT) || CONFIG_IS_ENABLED(LOAD_FIT_FULL)
	void *fdt_addr;
#endif
	u32 boot_device;
	u32 offset;
	u32 size;
	u32 flags;
	void *arg;
#ifdef CONFIG_SPL_LEGACY_IMAGE_CRC_CHECK
	ulong dcrc_data;
	ulong dcrc_length;
	ulong dcrc;
#endif
};

static inline void *spl_image_fdt_addr(struct spl_image_info *info)
{
#if CONFIG_IS_ENABLED(LOAD_FIT) || CONFIG_IS_ENABLED(LOAD_FIT_FULL)
	return info->fdt_addr;
#else
	return 0;
#endif
}

/**
 * Information required to load data from a device
 *
 * @dev: Pointer to the device, e.g. struct mmc *
 * @priv: Private data for the device
 * @bl_len: Block length for reading in bytes
 * @filename: Name of the fit image file.
 * @read: Function to call to read from the device
 */
struct spl_load_info {
	void *dev;
	void *priv;
	int bl_len;
	const char *filename;
	/**
	 * read() - Read from device
	 *
	 * @load: Information about the load state
	 * @sector: Sector number to read from (each @load->bl_len bytes)
	 * @count: Number of sectors to read
	 * @buf: Buffer to read into
	 * @return number of sectors read, 0 on error
	 */
	ulong (*read)(struct spl_load_info *load, ulong sector, ulong count,
		      void *buf);
};

/*
 * We need to know the position of U-Boot in memory so we can jump to it. We
 * allow any U-Boot binary to be used (u-boot.bin, u-boot-nodtb.bin,
 * u-boot.img), hence the '_any'. These is no checking here that the correct
 * image is found. For example if u-boot.img is used we don't check that
 * spl_parse_image_header() can parse a valid header.
 *
 * Similarly for SPL, so that TPL can jump to SPL.
 */
binman_sym_extern(ulong, u_boot_any, image_pos);
binman_sym_extern(ulong, u_boot_any, size);
binman_sym_extern(ulong, u_boot_spl_any, image_pos);
binman_sym_extern(ulong, u_boot_spl_any, size);
binman_sym_extern(ulong, u_boot_vpl_any, image_pos);
binman_sym_extern(ulong, u_boot_vpl_any, size);

/**
 * spl_get_image_pos() - get the image position of the next phase
 *
 * This returns the image position to use to load the next phase of U-Boot
 */
ulong spl_get_image_pos(void);

/**
 * spl_get_image_size() - get the size of the next phase
 *
 * This returns the size to use to load the next phase of U-Boot
 */
ulong spl_get_image_size(void);

/**
 * spl_get_image_text_base() - get the text base of the next phase
 *
 * This returns the address that the next stage is linked to run at, i.e.
 * CONFIG_SPL_TEXT_BASE or CONFIG_TEXT_BASE
 *
 * Return: text-base address
 */
ulong spl_get_image_text_base(void);

/**
 * spl_load_simple_fit_skip_processing() - Hook to allow skipping the FIT
 *	image processing during spl_load_simple_fit().
 *
 * Return true to skip FIT processing, false to preserve the full code flow
 * of spl_load_simple_fit().
 */
bool spl_load_simple_fit_skip_processing(void);

/**
 * spl_load_simple_fit_fix_load() - Hook to make fixes
 * after fit image header is loaded
 *
 * Returns pointer to fit
 */
void *spl_load_simple_fit_fix_load(const void *fit);

/**
 * spl_load_simple_fit() - Loads a fit image from a device.
 * @spl_image:	Image description to set up
 * @info:	Structure containing the information required to load data.
 * @sector:	Sector number where FIT image is located in the device
 * @fdt:	Pointer to the copied FIT header.
 *
 * Reads the FIT image @sector in the device. Loads u-boot image to
 * specified load address and copies the dtb to end of u-boot image.
 * Returns 0 on success.
 */
int spl_load_simple_fit(struct spl_image_info *spl_image,
			struct spl_load_info *info, ulong sector, void *fdt);

#define SPL_COPY_PAYLOAD_ONLY	1
#define SPL_FIT_FOUND		2

/**
 * spl_load_legacy_img() - Loads a legacy image from a device.
 * @spl_image:	Image description to set up
 * @load:	Structure containing the information required to load data.
 * @offset:	Pointer to image
 * @hdr:	Pointer to image header
 *
 * Reads an legacy image from the device. Loads u-boot image to
 * specified load address.
 * Returns 0 on success.
 */
int spl_load_legacy_img(struct spl_image_info *spl_image,
			struct spl_boot_device *bootdev,
			struct spl_load_info *load, ulong offset,
			struct legacy_img_hdr *hdr);


/**
 * spl_load_imx_container() - Loads a imx container image from a device.
 * @spl_image:	Image description to set up
 * @info:	Structure containing the information required to load data.
 * @sector:	Sector number where container image is located in the device
 *
 * Reads the container image @sector in the device. Loads u-boot image to
 * specified load address.
 */
int spl_load_imx_container(struct spl_image_info *spl_image,
			   struct spl_load_info *info, ulong sector);

/* SPL common functions */
void preloader_console_init(void);
u32 spl_boot_device(void);

struct spi_flash;

/**
 * spl_spi_get_uboot_offs() - Lookup function for the SPI boot offset
 * @flash: The spi flash to boot from
 *
 * Return: The offset of U-Boot within the SPI flash
 */
unsigned int spl_spi_get_uboot_offs(struct spi_flash *flash);

/**
 * spl_spi_boot_bus() - Lookup function for the SPI boot bus source.
 *
 * This function returns the SF bus to load from.
 * If not overridden, it is weakly defined in common/spl/spl_spi.c.
 */
u32 spl_spi_boot_bus(void);

/**
 * spl_spi_boot_cs() - Lookup function for the SPI boot CS source.
 *
 * This function returns the SF CS to load from.
 * If not overridden, it is weakly defined in common/spl/spl_spi.c.
 */
u32 spl_spi_boot_cs(void);

/**
 * spl_mmc_boot_mode() - Lookup function for the mode of an MMC boot source.
 * @boot_device:	ID of the device which the MMC driver wants to read
 *			from.  Common values are e.g. BOOT_DEVICE_MMC1,
 *			BOOT_DEVICE_MMC2, BOOT_DEVICE_MMC2_2.
 *
 * This function should return one of MMCSD_MODE_FS, MMCSD_MODE_EMMCBOOT, or
 * MMCSD_MODE_RAW for each MMC boot source which is defined for the target.  The
 * boot_device parameter tells which device the MMC driver is interested in.
 *
 * If not overridden, it is weakly defined in common/spl/spl_mmc.c.
 *
 * Note:  It is important to use the boot_device parameter instead of e.g.
 * spl_boot_device() as U-Boot is not always loaded from the same device as SPL.
 */
u32 spl_mmc_boot_mode(struct mmc *mmc, const u32 boot_device);

/**
 * spl_mmc_boot_partition() - MMC partition to load U-Boot from.
 * @boot_device:	ID of the device which the MMC driver wants to load
 *			U-Boot from.
 *
 * This function should return the partition number which the SPL
 * should load U-Boot from (on the given boot_device) when
 * CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION is set.
 *
 * If not overridden, it is weakly defined in common/spl/spl_mmc.c.
 */
int spl_mmc_boot_partition(const u32 boot_device);

struct mmc;
/**
 * default_spl_mmc_emmc_boot_partition() - eMMC boot partition to load U-Boot from.
 * mmc:			Pointer for the mmc device structure
 *
 * This function should return the eMMC boot partition number which
 * the SPL should load U-Boot from (on the given boot_device).
 */
int default_spl_mmc_emmc_boot_partition(struct mmc *mmc);

/**
 * spl_mmc_emmc_boot_partition() - eMMC boot partition to load U-Boot from.
 * mmc:			Pointer for the mmc device structure
 *
 * This function should return the eMMC boot partition number which
 * the SPL should load U-Boot from (on the given boot_device).
 *
 * If not overridden, it is weakly defined in common/spl/spl_mmc.c
 * and calls default_spl_mmc_emmc_boot_partition();
 */
int spl_mmc_emmc_boot_partition(struct mmc *mmc);

void spl_set_bd(void);

/**
 * spl_mmc_get_uboot_raw_sector() - Provide raw sector of the start of U-Boot (architecture override)
 *
 * This is a weak function which by default will provide the raw sector that is
 * where the start of the U-Boot image has been written to.
 *
 * @mmc: struct mmc that describes the devie where U-Boot resides
 * @raw_sect: The raw sector number where U-Boot is by default.
 * Return: The raw sector location that U-Boot resides at
 */
unsigned long arch_spl_mmc_get_uboot_raw_sector(struct mmc *mmc,
						unsigned long raw_sect);

/**
 * spl_mmc_get_uboot_raw_sector() - Provide raw sector of the start of U-Boot (board override)
 *
 * This is a weak function which by default will provide the raw sector that is
 * where the start of the U-Boot image has been written to.
 *
 * @mmc: struct mmc that describes the devie where U-Boot resides
 * @raw_sect: The raw sector number where U-Boot is by default.
 * Return: The raw sector location that U-Boot resides at
 */
unsigned long board_spl_mmc_get_uboot_raw_sector(struct mmc *mmc,
						 unsigned long raw_sect);

/**
 * spl_mmc_get_uboot_raw_sector() - Provide raw sector of the start of U-Boot
 *
 * This is a weak function which by default will provide the raw sector that is
 * where the start of the U-Boot image has been written to.
 *
 * @mmc: struct mmc that describes the devie where U-Boot resides
 * @raw_sect: The raw sector number where U-Boot is by default.
 * Return: The raw sector location that U-Boot resides at
 */
unsigned long spl_mmc_get_uboot_raw_sector(struct mmc *mmc,
					   unsigned long raw_sect);

/**
 * spl_set_header_raw_uboot() - Set up a standard SPL image structure
 *
 * This sets up the given spl_image which the standard values obtained from
 * config options: CONFIG_SYS_MONITOR_LEN, CONFIG_SYS_UBOOT_START,
 * CONFIG_TEXT_BASE.
 *
 * @spl_image: Image description to set up
 */
void spl_set_header_raw_uboot(struct spl_image_info *spl_image);

/**
 * spl_parse_image_header() - parse the image header and set up info
 *
 * This parses the legacy image header information at @header and sets up
 * @spl_image according to what is found. If no image header is found, then
 * a raw image or bootz is assumed. If CONFIG_SPL_PANIC_ON_RAW_IMAGE is
 * enabled, then this causes a panic. If CONFIG_SPL_RAW_IMAGE_SUPPORT is not
 * enabled then U-Boot gives up. Otherwise U-Boot sets up the image using
 * spl_set_header_raw_uboot(), or possibly the bootz header.
 *
 * @spl_image: Image description to set up
 * @header image header to parse
 * Return: 0 if a header was correctly parsed, -ve on error
 */
int spl_parse_image_header(struct spl_image_info *spl_image,
			   const struct spl_boot_device *bootdev,
			   const struct legacy_img_hdr *header);

void spl_board_prepare_for_linux(void);

/**
 * spl_board_prepare_for_optee() - Prepare board for an OPTEE payload
 *
 * Prepares the board for booting an OP-TEE payload. Initialization is platform
 * specific, and may include configuring the TrustZone memory, and other
 * initialization steps required by OP-TEE.
 * Note that @fdt is not used directly by OP-TEE. OP-TEE passes this @fdt to
 * its normal world target. This target is not guaranteed to be u-boot, so @fdt
 * changes that would normally be done by u-boot should be done in this step.
 *
 * @fdt: Devicetree that will be passed on, or NULL
 */
void spl_board_prepare_for_optee(void *fdt);
void spl_board_prepare_for_boot(void);
int spl_board_ubi_load_image(u32 boot_device);
int spl_board_boot_device(enum boot_device boot_dev_spl);

/**
 * spl_board_loader_name() - Return a name for the loader
 *
 * This is a weak function which might be overridden by the board code. With
 * that a board specific value for the device where the U-Boot will be loaded
 * from can be set. By default it returns NULL.
 *
 * @boot_device:	ID of the device which SPL wants to load U-Boot from.
 */
const char *spl_board_loader_name(u32 boot_device);

/**
 * jump_to_image_linux() - Jump to a Linux kernel from SPL
 *
 * This jumps into a Linux kernel using the information in @spl_image.
 *
 * @spl_image: Image description to set up
 */
void __noreturn jump_to_image_linux(struct spl_image_info *spl_image);

/**
 * jump_to_image_optee() - Jump to OP-TEE OS from SPL
 *
 * This jumps into OP-TEE OS using the information in @spl_image.
 *
 * @spl_image: Image description to set up
 */
void __noreturn jump_to_image_optee(struct spl_image_info *spl_image);

/**
 * spl_start_uboot() - Check if SPL should start the kernel or U-Boot
 *
 * This is called by the various SPL loaders to determine whether the board
 * wants to load the kernel or U-Boot. This function should be provided by
 * the board.
 *
 * Return: 0 if SPL should start the kernel, 1 if U-Boot must be started
 */
int spl_start_uboot(void);

/**
 * spl_display_print() - Display a board-specific message in SPL
 *
 * If CONFIG_SPL_DISPLAY_PRINT is enabled, U-Boot will call this function
 * immediately after displaying the SPL console banner ("U-Boot SPL ...").
 * This function should be provided by the board.
 */
void spl_display_print(void);

/**
 * struct spl_boot_device - Describes a boot device used by SPL
 *
 * @boot_device: A number indicating the BOOT_DEVICE type. There are various
 * BOOT_DEVICE... #defines and enums in U-Boot and they are not consistently
 * numbered.
 * @boot_device_name: Named boot device, or NULL if none.
 *
 * Note: Additional fields can be added here, bearing in mind that SPL is
 * size-sensitive and common fields will be present on all boards. This
 * struct can also be used to return additional information about the load
 * process if that becomes useful.
 */
struct spl_boot_device {
	uint boot_device;
	const char *boot_device_name;
};

/**
 * Holds information about a way of loading an SPL image
 *
 * @name: User-friendly name for this method (e.g. "MMC")
 * @boot_device: Boot device that this loader supports
 * @load_image: Function to call to load image
 */
struct spl_image_loader {
#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
	const char *name;
#endif
	uint boot_device;
	/**
	 * load_image() - Load an SPL image
	 *
	 * @spl_image: place to put image information
	 * @bootdev: describes the boot device to load from
	 */
	int (*load_image)(struct spl_image_info *spl_image,
			  struct spl_boot_device *bootdev);
};

/* Helper function for accessing the name */
static inline const char *spl_loader_name(const struct spl_image_loader *loader)
{
#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
	const char *name;
	name = spl_board_loader_name(loader->boot_device);
	return name ?: loader->name;
#else
	return NULL;
#endif
}

/* Declare an SPL image loader */
#define SPL_LOAD_IMAGE(__name)					\
	ll_entry_declare(struct spl_image_loader, __name, spl_image_loader)

/*
 * _priority is the priority of this method, 0 meaning it will be the top
 * choice for this device, 9 meaning it is the bottom choice.
 * _boot_device is the BOOT_DEVICE_... value
 * _method is the load_image function to call
 */
#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
#define SPL_LOAD_IMAGE_METHOD(_name, _priority, _boot_device, _method) \
	SPL_LOAD_IMAGE(_boot_device ## _priority ## _method) = { \
		.name = _name, \
		.boot_device = _boot_device, \
		.load_image = _method, \
	}
#else
#define SPL_LOAD_IMAGE_METHOD(_name, _priority, _boot_device, _method) \
	SPL_LOAD_IMAGE(_boot_device ## _priority ## _method) = { \
		.boot_device = _boot_device, \
		.load_image = _method, \
	}
#endif

#define SPL_LOAD_IMAGE_GET(_priority, _boot_device, _method) \
	ll_entry_get(struct spl_image_loader, \
		     _boot_device ## _priority ## _method, spl_image_loader)

/* SPL FAT image functions */

/**
 * spl_fat_force_reregister() - Force reregistration of FAT block devices
 *
 * To avoid repeatedly looking up block devices, spl_load_image_fat keeps track
 * of whether it has already registered a block device. This is fine for most
 * cases, but when running unit tests all devices are removed and recreated
 * in-between tests. This function will force re-registration of any block
 * devices, ensuring that we don't try to use an invalid block device.
 */
void spl_fat_force_reregister(void);

int spl_load_image_fat(struct spl_image_info *spl_image,
		       struct spl_boot_device *bootdev,
		       struct blk_desc *block_dev, int partition,
		       const char *filename);
int spl_load_image_fat_os(struct spl_image_info *spl_image,
			  struct spl_boot_device *bootdev,
			  struct blk_desc *block_dev, int partition);

void __noreturn jump_to_image_no_args(struct spl_image_info *spl_image);

/* SPL EXT image functions */
int spl_load_image_ext(struct spl_image_info *spl_image,
		       struct spl_boot_device *bootdev,
		       struct blk_desc *block_dev, int partition,
		       const char *filename);
int spl_load_image_ext_os(struct spl_image_info *spl_image,
			  struct spl_boot_device *bootdev,
			  struct blk_desc *block_dev, int partition);
int spl_blk_load_image(struct spl_image_info *spl_image,
		       struct spl_boot_device *bootdev,
		       enum uclass_id uclass_id, int devnum, int partnum);

/**
 * spl_early_init() - Set up device tree and driver model in SPL if enabled
 *
 * Call this function in board_init_f() if you want to use device tree and
 * driver model early, before board_init_r() is called.
 *
 * If this is not called, then driver model will be inactive in SPL's
 * board_init_f(), and no device tree will be available.
 */
int spl_early_init(void);

/**
 * spl_init() - Set up device tree and driver model in SPL if enabled
 *
 * You can optionally call spl_early_init(), then optionally call spl_init().
 * This function will be called from board_init_r() if not called earlier.
 *
 * Both spl_early_init() and spl_init() perform a similar function except that
 * the latter will not set up the malloc() area if
 * CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN is enabled, since it is assumed to
 * already be done by a calll to spl_relocate_stack_gd() before board_init_r()
 * is reached.
 *
 * This function will be called from board_init_r() if not called earlier.
 *
 * If this is not called, then driver model will be inactive in SPL's
 * board_init_f(), and no device tree will be available.
 */
int spl_init(void);

/*
 * spl_board_init() - Do board-specific init in SPL
 *
 * If xPL_BOARD_INIT is enabled, this is called from board_init_r() before
 * jumping to the next phase.
 */
void spl_board_init(void);

/**
 * spl_was_boot_source() - check if U-Boot booted from SPL
 *
 * This will normally be true, but if U-Boot jumps to second U-Boot, it will
 * be false. This should be implemented by board-specific code.
 *
 * Return: true if U-Boot booted from SPL, else false
 */
bool spl_was_boot_source(void);

/**
 * spl_dfu_cmd- run dfu command with chosen mmc device interface
 * @param usb_index - usb controller number
 * @param mmc_dev -  mmc device nubmer
 *
 * Return: 0 on success, otherwise error code
 */
int spl_dfu_cmd(int usbctrl, char *dfu_alt_info, char *interface, char *devstr);

/**
 * spl_mmc_clear_cache() - Clear cached MMC devices
 *
 * To avoid reinitializing MMCs, spl_mmc_load caches the most-recently-used MMC
 * device. This is fine for most cases, but when running unit tests all devices
 * are removed and recreated in-between tests. This function will clear any
 * cached state, ensuring that we don't try to use an invalid MMC.
 */
void spl_mmc_clear_cache(void);

int spl_mmc_load_image(struct spl_image_info *spl_image,
		       struct spl_boot_device *bootdev);

/**
 * spl_mmc_load() - Load an image file from MMC/SD media
 *
 * @param spl_image	Image data filled in by loading process
 * @param bootdev	Describes which device to load from
 * @param filename	Name of file to load (in FS mode)
 * @param raw_part	Partition to load from (in RAW mode)
 * @param raw_sect	Sector to load from (in RAW mode)
 *
 * Return: 0 on success, otherwise error code
 */
int spl_mmc_load(struct spl_image_info *spl_image,
		 struct spl_boot_device *bootdev,
		 const char *filename,
		 int raw_part,
		 unsigned long raw_sect);

/**
 * spl_usb_load() - Load an image file from USB mass storage
 *
 * @param spl_image	Image data filled in by loading process
 * @param bootdev	Describes which device to load from
 * @param raw_part	Fat partition to load from
 * @param filename	Name of file to load
 *
 * Return: 0 on success, otherwise error code
 */
int spl_usb_load(struct spl_image_info *spl_image,
		 struct spl_boot_device *bootdev,
		 int partition, const char *filename);

int spl_ymodem_load_image(struct spl_image_info *spl_image,
			  struct spl_boot_device *bootdev);

/**
 * spl_invoke_atf - boot using an ARM trusted firmware image
 */
void __noreturn spl_invoke_atf(struct spl_image_info *spl_image);

/**
 * bl2_plat_get_bl31_params() - return params for bl31.
 * @bl32_entry:	address of BL32 executable (secure)
 * @bl33_entry:	address of BL33 executable (non secure)
 * @fdt_addr:	address of Flat Device Tree
 *
 * This is a weak function which might be overridden by the board code. By
 * default it will just call bl2_plat_get_bl31_params_default().
 *
 * If you just want to manipulate or add some parameters, you can override
 * this function, call bl2_plat_get_bl31_params_default and operate on the
 * returned bl31 params.
 *
 * Return: bl31 params structure pointer
 */
struct bl31_params *bl2_plat_get_bl31_params(uintptr_t bl32_entry,
					     uintptr_t bl33_entry,
					     uintptr_t fdt_addr);

/**
 * bl2_plat_get_bl31_params_default() - prepare params for bl31.
 * @bl32_entry:	address of BL32 executable (secure)
 * @bl33_entry:	address of BL33 executable (non secure)
 * @fdt_addr:	address of Flat Device Tree
 *
 * This is the default implementation of bl2_plat_get_bl31_params(). It assigns
 * a pointer to the memory that the platform has kept aside to pass platform
 * specific and trusted firmware related information to BL31. This memory is
 * allocated by allocating memory to bl2_to_bl31_params_mem structure which is
 * a superset of all the structure whose information is passed to BL31
 *
 * NOTE: The memory is statically allocated, thus this function should be
 * called only once. All subsequent calls will overwrite any changes.
 *
 * Return: bl31 params structure pointer
 */
struct bl31_params *bl2_plat_get_bl31_params_default(uintptr_t bl32_entry,
						     uintptr_t bl33_entry,
						     uintptr_t fdt_addr);

/**
 * bl2_plat_get_bl31_params_v2() - return params for bl31
 * @bl32_entry:	address of BL32 executable (secure)
 * @bl33_entry:	address of BL33 executable (non secure)
 * @fdt_addr:	address of Flat Device Tree
 *
 * This function does the same as bl2_plat_get_bl31_params() except that is is
 * used for the new LOAD_IMAGE_V2 option, which uses a slightly different
 * method to pass the parameters.
 *
 * Return: bl31 params structure pointer
 */
struct bl_params *bl2_plat_get_bl31_params_v2(uintptr_t bl32_entry,
					      uintptr_t bl33_entry,
					      uintptr_t fdt_addr);

/**
 * bl2_plat_get_bl31_params_v2_default() - prepare params for bl31.
 * @bl32_entry:	address of BL32 executable (secure)
 * @bl33_entry:	address of BL33 executable (non secure)
 * @fdt_addr:	address of Flat Device Tree
 *
 * This is the default implementation of bl2_plat_get_bl31_params_v2(). It
 * prepares the linked list of the bl31 params, populates the image types and
 * set the entry points for bl32 and bl33 (if available).
 *
 * NOTE: The memory is statically allocated, thus this function should be
 * called only once. All subsequent calls will overwrite any changes.
 *
 * Return: bl31 params structure pointer
 */
struct bl_params *bl2_plat_get_bl31_params_v2_default(uintptr_t bl32_entry,
						      uintptr_t bl33_entry,
						      uintptr_t fdt_addr);
/**
 * spl_optee_entry - entry function for optee
 *
 * args defind in op-tee project
 * https://github.com/OP-TEE/optee_os/
 * core/arch/arm/kernel/generic_entry_a32.S
 * @arg0: pagestore
 * @arg1: (ARMv7 standard bootarg #1)
 * @arg2: device tree address, (ARMv7 standard bootarg #2)
 * @arg3: non-secure entry address (ARMv7 bootarg #0)
 */
void __noreturn spl_optee_entry(void *arg0, void *arg1, void *arg2, void *arg3);

/**
 * spl_invoke_opensbi - boot using a RISC-V OpenSBI image
 */
void __noreturn spl_invoke_opensbi(struct spl_image_info *spl_image);

/**
 * board_return_to_bootrom - allow for boards to continue with the boot ROM
 *
 * If a board (e.g. the Rockchip RK3368 boards) provide some
 * supporting functionality for SPL in their boot ROM and the SPL
 * stage wants to return to the ROM code to continue booting, boards
 * can implement 'board_return_to_bootrom'.
 */
int board_return_to_bootrom(struct spl_image_info *spl_image,
			    struct spl_boot_device *bootdev);

/**
 * board_spl_fit_size_align - specific size align before processing payload
 *
 */
ulong board_spl_fit_size_align(ulong size);

/**
 * spl_perform_fixups() - arch/board-specific callback before processing
 *                        the boot-payload
 */
void spl_perform_fixups(struct spl_image_info *spl_image);

/*
 * spl_get_load_buffer() - get buffer for loading partial image data
 *
 * Returns memory area which can be populated by partial image data,
 * ie. uImage or fitImage header.
 */
struct legacy_img_hdr *spl_get_load_buffer(ssize_t offset, size_t size);

/**
 * board_spl_fit_append_fdt_skip(): test whether DTO application should be skipped
 * @name:	DTO node name within fitImage images node
 *
 * A board-specific function used to indicate whether a DTO from fitImage
 * configuration node 'fdt' property DT and DTO list should be applied onto
 * the base DT or not applied.
 *
 * This is useful in case of DTOs which implement e.g. different board revision
 * details, where such DTO should be applied on one board revision, and should
 * not be applied on another board revision.
 *
 * Return:	0 to indicate DTO is not skipped, all else to indicate DTO is skipped.
 */
int board_spl_fit_append_fdt_skip(const char *name);

void board_boot_order(u32 *spl_boot_list);
void spl_save_restore_data(void);

/**
 * spl_load_fit_image() - Fully parse and a FIT image in SPL
 *
 * @spl_image: SPL Image data to fill in
 * @header: Pointer to FIT image
 * Return 0 if OK, -ve on error
 */
int spl_load_fit_image(struct spl_image_info *spl_image,
		       const struct legacy_img_hdr *header);

/*
 * spl_decompression_enabled() - check decompression support is enabled for SPL build
 *
 * Returns  true  if decompression support is enabled, else False
 */
static inline bool spl_decompression_enabled(void)
{
	return IS_ENABLED(CONFIG_SPL_GZIP) || IS_ENABLED(CONFIG_SPL_LZMA);
}
#endif