xref: /openbmc/u-boot/env/fat.c (revision 14453fbfadc2f98ca35d6033140466c7a4b4947a)
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  
11  #include <command.h>
12  #include <environment.h>
13  #include <linux/stddef.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  
21  #ifdef CONFIG_SPL_BUILD
22  /* TODO(sjg@chromium.org): Figure out why this is needed */
23  # if !defined(CONFIG_TARGET_AM335X_EVM) || defined(CONFIG_SPL_OS_BOOT)
24  #  define LOADENV
25  # endif
26  #else
27  # define LOADENV
28  # if defined(CONFIG_CMD_SAVEENV)
29  #  define CMD_SAVEENV
30  # endif
31  #endif
32  
33  #ifdef CMD_SAVEENV
34  static int env_fat_save(void)
35  {
36  	env_t __aligned(ARCH_DMA_MINALIGN) env_new;
37  	struct blk_desc *dev_desc = NULL;
38  	disk_partition_t info;
39  	int dev, part;
40  	int err;
41  	loff_t size;
42  
43  	err = env_export(&env_new);
44  	if (err)
45  		return err;
46  
47  	part = blk_get_device_part_str(CONFIG_ENV_FAT_INTERFACE,
48  					CONFIG_ENV_FAT_DEVICE_AND_PART,
49  					&dev_desc, &info, 1);
50  	if (part < 0)
51  		return 1;
52  
53  	dev = dev_desc->devnum;
54  	if (fat_set_blk_dev(dev_desc, &info) != 0) {
55  		/*
56  		 * This printf is embedded in the messages from env_save that
57  		 * will calling it. The missing \n is intentional.
58  		 */
59  		printf("Unable to use %s %d:%d... ",
60  		       CONFIG_ENV_FAT_INTERFACE, dev, part);
61  		return 1;
62  	}
63  
64  	err = file_fat_write(CONFIG_ENV_FAT_FILE, (void *)&env_new, 0, sizeof(env_t),
65  			     &size);
66  	if (err == -1) {
67  		/*
68  		 * This printf is embedded in the messages from env_save that
69  		 * will calling it. The missing \n is intentional.
70  		 */
71  		printf("Unable to write \"%s\" from %s%d:%d... ",
72  			CONFIG_ENV_FAT_FILE, CONFIG_ENV_FAT_INTERFACE, dev, part);
73  		return 1;
74  	}
75  
76  	return 0;
77  }
78  #endif /* CMD_SAVEENV */
79  
80  #ifdef LOADENV
81  static int env_fat_load(void)
82  {
83  	ALLOC_CACHE_ALIGN_BUFFER(char, buf, CONFIG_ENV_SIZE);
84  	struct blk_desc *dev_desc = NULL;
85  	disk_partition_t info;
86  	int dev, part;
87  	int err;
88  
89  #ifdef CONFIG_MMC
90  	if (!strcmp(CONFIG_ENV_FAT_INTERFACE, "mmc"))
91  		mmc_initialize(NULL);
92  #endif
93  
94  	part = blk_get_device_part_str(CONFIG_ENV_FAT_INTERFACE,
95  					CONFIG_ENV_FAT_DEVICE_AND_PART,
96  					&dev_desc, &info, 1);
97  	if (part < 0)
98  		goto err_env_relocate;
99  
100  	dev = dev_desc->devnum;
101  	if (fat_set_blk_dev(dev_desc, &info) != 0) {
102  		/*
103  		 * This printf is embedded in the messages from env_save that
104  		 * will calling it. The missing \n is intentional.
105  		 */
106  		printf("Unable to use %s %d:%d... ",
107  		       CONFIG_ENV_FAT_INTERFACE, dev, part);
108  		goto err_env_relocate;
109  	}
110  
111  	err = file_fat_read(CONFIG_ENV_FAT_FILE, buf, CONFIG_ENV_SIZE);
112  	if (err == -1) {
113  		/*
114  		 * This printf is embedded in the messages from env_save that
115  		 * will calling it. The missing \n is intentional.
116  		 */
117  		printf("Unable to read \"%s\" from %s%d:%d... ",
118  			CONFIG_ENV_FAT_FILE, CONFIG_ENV_FAT_INTERFACE, dev, part);
119  		goto err_env_relocate;
120  	}
121  
122  	return env_import(buf, 1);
123  
124  err_env_relocate:
125  	set_default_env(NULL, 0);
126  
127  	return -EIO;
128  }
129  #endif /* LOADENV */
130  
131  U_BOOT_ENV_LOCATION(fat) = {
132  	.location	= ENVL_FAT,
133  	ENV_NAME("FAT")
134  #ifdef LOADENV
135  	.load		= env_fat_load,
136  #endif
137  #ifdef CMD_SAVEENV
138  	.save		= env_save_ptr(env_fat_save),
139  #endif
140  };
141