1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * (C) Copyright 2014
4  * Texas Instruments, <www.ti.com>
5  *
6  * Dan Murphy <dmurphy@ti.com>
7  *
8  * FAT Image Functions copied from spl_mmc.c
9  */
10 
11 #include <env.h>
12 #include <log.h>
13 #include <spl.h>
14 #include <spl_load.h>
15 #include <fat.h>
16 #include <errno.h>
17 #include <image.h>
18 #include <linux/libfdt.h>
19 #include <asm/cache.h>
20 
21 static int fat_registered;
22 
spl_fat_force_reregister(void)23 void spl_fat_force_reregister(void)
24 {
25 	fat_registered = 0;
26 }
27 
spl_register_fat_device(struct blk_desc * block_dev,int partition)28 static int spl_register_fat_device(struct blk_desc *block_dev, int partition)
29 {
30 	int err = 0;
31 
32 	if (fat_registered)
33 		return err;
34 
35 	err = fat_register_device(block_dev, partition);
36 	if (err) {
37 #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
38 		printf("%s: fat register err - %d\n", __func__, err);
39 #endif
40 		return err;
41 	}
42 
43 	fat_registered = 1;
44 
45 	return err;
46 }
47 
spl_fit_read(struct spl_load_info * load,ulong file_offset,ulong size,void * buf)48 static ulong spl_fit_read(struct spl_load_info *load, ulong file_offset,
49 			  ulong size, void *buf)
50 {
51 	struct legacy_img_hdr *header;
52 	loff_t actread;
53 	int ret;
54 	char *filename = load->priv;
55 
56 	ret = fat_read_file(filename, buf, file_offset, size, &actread);
57 	if (ret)
58 		return ret;
59 
60 	if (CONFIG_IS_ENABLED(OS_BOOT)) {
61 		header = (struct legacy_img_hdr *)buf;
62 		if (image_get_magic(header) != FDT_MAGIC)
63 			return size;
64 	}
65 
66 	return actread;
67 }
68 
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)69 int spl_load_image_fat(struct spl_image_info *spl_image,
70 		       struct spl_boot_device *bootdev,
71 		       struct blk_desc *block_dev, int partition,
72 		       const char *filename)
73 {
74 	int err;
75 	loff_t size;
76 	struct spl_load_info load;
77 
78 	err = spl_register_fat_device(block_dev, partition);
79 	if (err)
80 		goto end;
81 
82 	/*
83 	 * Avoid pulling in this function for other image types since we are
84 	 * very short on space on some boards.
85 	 */
86 	if (IS_ENABLED(CONFIG_SPL_LOAD_FIT_FULL)) {
87 		err = fat_size(filename, &size);
88 		if (err)
89 			goto end;
90 	} else {
91 		size = 0;
92 	}
93 
94 	spl_load_init(&load, spl_fit_read, (void *)filename,
95 		      IS_ENABLED(CONFIG_SPL_FS_FAT_DMA_ALIGN) ?
96 		      ARCH_DMA_MINALIGN : 1);
97 
98 	err = spl_load(spl_image, bootdev, &load, size, 0);
99 
100 end:
101 #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
102 	if (err < 0)
103 		printf("%s: error reading image %s, err - %d\n",
104 		       __func__, filename, err);
105 #endif
106 
107 	return err;
108 }
109 
110 #if CONFIG_IS_ENABLED(OS_BOOT)
spl_load_image_fat_os(struct spl_image_info * spl_image,struct spl_boot_device * bootdev,struct blk_desc * block_dev,int partition)111 int spl_load_image_fat_os(struct spl_image_info *spl_image,
112 			  struct spl_boot_device *bootdev,
113 			  struct blk_desc *block_dev, int partition)
114 {
115 	int err;
116 	__maybe_unused char *file;
117 
118 	err = spl_register_fat_device(block_dev, partition);
119 	if (err)
120 		return err;
121 
122 #if defined(CONFIG_SPL_ENV_SUPPORT) && defined(CONFIG_SPL_OS_BOOT)
123 	file = env_get("falcon_args_file");
124 	if (file) {
125 		err = file_fat_read(file, (void *)CONFIG_SPL_PAYLOAD_ARGS_ADDR, 0);
126 		if (err <= 0) {
127 			printf("spl: error reading image %s, err - %d, falling back to default\n",
128 			       file, err);
129 			goto defaults;
130 		}
131 		file = env_get("falcon_image_file");
132 		if (file) {
133 			err = spl_load_image_fat(spl_image, bootdev, block_dev,
134 						 partition, file);
135 			if (err != 0) {
136 				puts("spl: falling back to default\n");
137 				goto defaults;
138 			}
139 
140 			return 0;
141 		} else
142 			puts("spl: falcon_image_file not set in environment, falling back to default\n");
143 	} else
144 		puts("spl: falcon_args_file not set in environment, falling back to default\n");
145 
146 defaults:
147 #endif
148 
149 	err = file_fat_read(CONFIG_SPL_FS_LOAD_ARGS_NAME,
150 			    (void *)CONFIG_SPL_PAYLOAD_ARGS_ADDR, 0);
151 	if (err <= 0) {
152 #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
153 		printf("%s: error reading image %s, err - %d\n",
154 		       __func__, CONFIG_SPL_FS_LOAD_ARGS_NAME, err);
155 #endif
156 		return -1;
157 	}
158 
159 	return spl_load_image_fat(spl_image, bootdev, block_dev, partition,
160 			CONFIG_SPL_FS_LOAD_KERNEL_NAME);
161 }
162 #else
spl_load_image_fat_os(struct spl_image_info * spl_image,struct spl_boot_device * bootdev,struct blk_desc * block_dev,int partition)163 int spl_load_image_fat_os(struct spl_image_info *spl_image,
164 			  struct spl_boot_device *bootdev,
165 			  struct blk_desc *block_dev, int partition)
166 {
167 	return -ENOSYS;
168 }
169 #endif
170