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