1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * (c) Copyright 2011 by Tigris Elektronik GmbH
4  *
5  * Author:
6  *  Maximilian Schwerin <mvs@tigris.de>
7  */
8 
9 #include <common.h>
10 #include <command.h>
11 #include <env.h>
12 #include <env_internal.h>
13 #include <part.h>
14 #include <malloc.h>
15 #include <memalign.h>
16 #include <search.h>
17 #include <errno.h>
18 #include <fat.h>
19 #include <mmc.h>
20 #include <asm/cache.h>
21 #include <linux/stddef.h>
22 
23 #ifdef CONFIG_SPL_BUILD
24 /* TODO(sjg@chromium.org): Figure out why this is needed */
25 # if !defined(CONFIG_TARGET_AM335X_EVM) || defined(CONFIG_SPL_OS_BOOT)
26 #  define LOADENV
27 # endif
28 #else
29 # define LOADENV
30 #endif
31 
env_fat_save(void)32 static int env_fat_save(void)
33 {
34 	env_t __aligned(ARCH_DMA_MINALIGN) env_new;
35 	struct blk_desc *dev_desc = NULL;
36 	struct disk_partition info;
37 	int dev, part;
38 	int err;
39 	loff_t size;
40 
41 	err = env_export(&env_new);
42 	if (err)
43 		return err;
44 
45 	part = blk_get_device_part_str(CONFIG_ENV_FAT_INTERFACE,
46 					CONFIG_ENV_FAT_DEVICE_AND_PART,
47 					&dev_desc, &info, 1);
48 	if (part < 0)
49 		return 1;
50 
51 	dev = dev_desc->devnum;
52 	if (fat_set_blk_dev(dev_desc, &info) != 0) {
53 		/*
54 		 * This printf is embedded in the messages from env_save that
55 		 * will calling it. The missing \n is intentional.
56 		 */
57 		printf("Unable to use %s %d:%d... ",
58 		       CONFIG_ENV_FAT_INTERFACE, dev, part);
59 		return 1;
60 	}
61 
62 	err = file_fat_write(CONFIG_ENV_FAT_FILE, (void *)&env_new, 0, sizeof(env_t),
63 			     &size);
64 	if (err == -1) {
65 		/*
66 		 * This printf is embedded in the messages from env_save that
67 		 * will calling it. The missing \n is intentional.
68 		 */
69 		printf("Unable to write \"%s\" from %s%d:%d... ",
70 			CONFIG_ENV_FAT_FILE, CONFIG_ENV_FAT_INTERFACE, dev, part);
71 		return 1;
72 	}
73 
74 	return 0;
75 }
76 
77 #ifdef LOADENV
env_fat_load(void)78 static int env_fat_load(void)
79 {
80 	ALLOC_CACHE_ALIGN_BUFFER(char, buf, CONFIG_ENV_SIZE);
81 	struct blk_desc *dev_desc = NULL;
82 	struct disk_partition info;
83 	int dev, part;
84 	int err;
85 
86 #ifdef CONFIG_MMC
87 	if (!strcmp(CONFIG_ENV_FAT_INTERFACE, "mmc"))
88 		mmc_initialize(NULL);
89 #endif
90 
91 	part = blk_get_device_part_str(CONFIG_ENV_FAT_INTERFACE,
92 					CONFIG_ENV_FAT_DEVICE_AND_PART,
93 					&dev_desc, &info, 1);
94 	if (part < 0)
95 		goto err_env_relocate;
96 
97 	dev = dev_desc->devnum;
98 	if (fat_set_blk_dev(dev_desc, &info) != 0) {
99 		/*
100 		 * This printf is embedded in the messages from env_save that
101 		 * will calling it. The missing \n is intentional.
102 		 */
103 		printf("Unable to use %s %d:%d... ",
104 		       CONFIG_ENV_FAT_INTERFACE, dev, part);
105 		goto err_env_relocate;
106 	}
107 
108 	err = file_fat_read(CONFIG_ENV_FAT_FILE, buf, CONFIG_ENV_SIZE);
109 	if (err == -1) {
110 		/*
111 		 * This printf is embedded in the messages from env_save that
112 		 * will calling it. The missing \n is intentional.
113 		 */
114 		printf("Unable to read \"%s\" from %s%d:%d... ",
115 			CONFIG_ENV_FAT_FILE, CONFIG_ENV_FAT_INTERFACE, dev, part);
116 		goto err_env_relocate;
117 	}
118 
119 	return env_import(buf, 1);
120 
121 err_env_relocate:
122 	env_set_default(NULL, 0);
123 
124 	return -EIO;
125 }
126 #endif /* LOADENV */
127 
128 U_BOOT_ENV_LOCATION(fat) = {
129 	.location	= ENVL_FAT,
130 	ENV_NAME("FAT")
131 #ifdef LOADENV
132 	.load		= env_fat_load,
133 #endif
134 	.save		= ENV_SAVE_PTR(env_fat_save),
135 };
136