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