1// SPDX-License-Identifier: GPL-2.0+
2
3#include <common.h>
4#include <env.h>
5#include <part.h>
6#include <spl.h>
7#include <spl_load.h>
8#include <asm/u-boot.h>
9#include <ext4fs.h>
10#include <errno.h>
11#include <image.h>
12
13static ulong spl_fit_read(struct spl_load_info *load, ulong file_offset,
14			  ulong size, void *buf)
15{
16	int ret;
17	loff_t actlen;
18
19	ret = ext4fs_read(buf, file_offset, size, &actlen);
20	if (ret)
21		return ret;
22	return actlen;
23}
24
25int spl_load_image_ext(struct spl_image_info *spl_image,
26		       struct spl_boot_device *bootdev,
27		       struct blk_desc *block_dev, int partition,
28		       const char *filename)
29{
30	s32 err;
31	loff_t filelen;
32	struct disk_partition part_info = {};
33	struct spl_load_info load;
34
35	if (part_get_info(block_dev, partition, &part_info)) {
36		printf("spl: no partition table found\n");
37		return -1;
38	}
39
40	ext4fs_set_blk_dev(block_dev, &part_info);
41
42	err = ext4fs_mount();
43	if (!err) {
44#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
45		printf("%s: ext4fs mount err - %d\n", __func__, err);
46#endif
47		return -1;
48	}
49
50	err = ext4fs_open(filename, &filelen);
51	if (err < 0) {
52		puts("spl: ext4fs_open failed\n");
53		goto end;
54	}
55
56	spl_set_bl_len(&load, 1);
57	load.read = spl_fit_read;
58	err = spl_load(spl_image, bootdev, &load, filelen, 0);
59
60end:
61#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
62	if (err < 0)
63		printf("%s: error reading image %s, err - %d\n",
64		       __func__, filename, err);
65#endif
66
67	return err < 0;
68}
69
70#if CONFIG_IS_ENABLED(OS_BOOT)
71int spl_load_image_ext_os(struct spl_image_info *spl_image,
72			  struct spl_boot_device *bootdev,
73			  struct blk_desc *block_dev, int partition)
74{
75	int err;
76	__maybe_unused loff_t filelen, actlen;
77	struct disk_partition part_info = {};
78	__maybe_unused char *file;
79
80	if (part_get_info(block_dev, partition, &part_info)) {
81		printf("spl: no partition table found\n");
82		return -1;
83	}
84
85	ext4fs_set_blk_dev(block_dev, &part_info);
86
87	err = ext4fs_mount();
88	if (!err) {
89#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
90		printf("%s: ext4fs mount err - %d\n", __func__, err);
91#endif
92		return -1;
93	}
94#if defined(CONFIG_SPL_ENV_SUPPORT)
95	file = env_get("falcon_args_file");
96	if (file) {
97		err = ext4fs_open(file, &filelen);
98		if (err < 0) {
99			puts("spl: ext4fs_open failed\n");
100			goto defaults;
101		}
102		err = ext4fs_read((void *)CONFIG_SPL_PAYLOAD_ARGS_ADDR, 0, filelen, &actlen);
103		if (err < 0) {
104			printf("spl: error reading image %s, err - %d, falling back to default\n",
105			       file, err);
106			goto defaults;
107		}
108		file = env_get("falcon_image_file");
109		if (file) {
110			err = spl_load_image_ext(spl_image, bootdev, block_dev,
111						 partition, file);
112			if (err != 0) {
113				puts("spl: falling back to default\n");
114				goto defaults;
115			}
116
117			return 0;
118		} else {
119			puts("spl: falcon_image_file not set in environment, falling back to default\n");
120		}
121	} else {
122		puts("spl: falcon_args_file not set in environment, falling back to default\n");
123	}
124
125defaults:
126#endif
127
128	err = ext4fs_open(CONFIG_SPL_FS_LOAD_ARGS_NAME, &filelen);
129	if (err < 0)
130		puts("spl: ext4fs_open failed\n");
131
132	err = ext4fs_read((void *)CONFIG_SPL_PAYLOAD_ARGS_ADDR, 0, filelen, &actlen);
133	if (err < 0) {
134#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
135		printf("%s: error reading image %s, err - %d\n",
136		       __func__, CONFIG_SPL_FS_LOAD_ARGS_NAME, err);
137#endif
138		return -1;
139	}
140
141	return spl_load_image_ext(spl_image, bootdev, block_dev, partition,
142			CONFIG_SPL_FS_LOAD_KERNEL_NAME);
143}
144#else
145int spl_load_image_ext_os(struct spl_image_info *spl_image,
146			  struct spl_boot_device *bootdev,
147			  struct blk_desc *block_dev, int partition)
148{
149	return -ENOSYS;
150}
151#endif
152