Merge https://gitlab.denx.de/u-boot/custodians/u-boot-sh
[platform/kernel/u-boot.git] / env / fat.c
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
32 __weak int mmc_get_env_dev(void)
33 {
34 #ifdef CONFIG_SYS_MMC_ENV_DEV
35         return CONFIG_SYS_MMC_ENV_DEV;
36 #else
37         return 0;
38 #endif
39 }
40
41 static char *env_fat_device_and_part(void)
42 {
43 #ifdef CONFIG_MMC
44         static char *part_str;
45
46         if (!part_str) {
47                 part_str = CONFIG_ENV_FAT_DEVICE_AND_PART;
48                 if (!strcmp(CONFIG_ENV_FAT_INTERFACE, "mmc") && part_str[0] == ':') {
49                         part_str = "0" CONFIG_ENV_FAT_DEVICE_AND_PART;
50                         part_str[0] += mmc_get_env_dev();
51                 }
52         }
53
54         return part_str;
55 #else
56         return CONFIG_ENV_FAT_DEVICE_AND_PART;
57 #endif
58 }
59
60 static int env_fat_save(void)
61 {
62         env_t __aligned(ARCH_DMA_MINALIGN) env_new;
63         struct blk_desc *dev_desc = NULL;
64         struct disk_partition info;
65         int dev, part;
66         int err;
67         loff_t size;
68
69         err = env_export(&env_new);
70         if (err)
71                 return err;
72
73         part = blk_get_device_part_str(CONFIG_ENV_FAT_INTERFACE,
74                                         env_fat_device_and_part(),
75                                         &dev_desc, &info, 1);
76         if (part < 0)
77                 return 1;
78
79         dev = dev_desc->devnum;
80         if (fat_set_blk_dev(dev_desc, &info) != 0) {
81                 /*
82                  * This printf is embedded in the messages from env_save that
83                  * will calling it. The missing \n is intentional.
84                  */
85                 printf("Unable to use %s %d:%d... ",
86                        CONFIG_ENV_FAT_INTERFACE, dev, part);
87                 return 1;
88         }
89
90         err = file_fat_write(CONFIG_ENV_FAT_FILE, (void *)&env_new, 0, sizeof(env_t),
91                              &size);
92         if (err == -1) {
93                 /*
94                  * This printf is embedded in the messages from env_save that
95                  * will calling it. The missing \n is intentional.
96                  */
97                 printf("Unable to write \"%s\" from %s%d:%d... ",
98                         CONFIG_ENV_FAT_FILE, CONFIG_ENV_FAT_INTERFACE, dev, part);
99                 return 1;
100         }
101
102         return 0;
103 }
104
105 #ifdef LOADENV
106 static int env_fat_load(void)
107 {
108         ALLOC_CACHE_ALIGN_BUFFER(char, buf, CONFIG_ENV_SIZE);
109         struct blk_desc *dev_desc = NULL;
110         struct disk_partition info;
111         int dev, part;
112         int err;
113
114 #ifdef CONFIG_MMC
115         if (!strcmp(CONFIG_ENV_FAT_INTERFACE, "mmc"))
116                 mmc_initialize(NULL);
117 #endif
118
119         part = blk_get_device_part_str(CONFIG_ENV_FAT_INTERFACE,
120                                         env_fat_device_and_part(),
121                                         &dev_desc, &info, 1);
122         if (part < 0)
123                 goto err_env_relocate;
124
125         dev = dev_desc->devnum;
126         if (fat_set_blk_dev(dev_desc, &info) != 0) {
127                 /*
128                  * This printf is embedded in the messages from env_save that
129                  * will calling it. The missing \n is intentional.
130                  */
131                 printf("Unable to use %s %d:%d... ",
132                        CONFIG_ENV_FAT_INTERFACE, dev, part);
133                 goto err_env_relocate;
134         }
135
136         err = file_fat_read(CONFIG_ENV_FAT_FILE, buf, CONFIG_ENV_SIZE);
137         if (err == -1) {
138                 /*
139                  * This printf is embedded in the messages from env_save that
140                  * will calling it. The missing \n is intentional.
141                  */
142                 printf("Unable to read \"%s\" from %s%d:%d... ",
143                         CONFIG_ENV_FAT_FILE, CONFIG_ENV_FAT_INTERFACE, dev, part);
144                 goto err_env_relocate;
145         }
146
147         return env_import(buf, 1);
148
149 err_env_relocate:
150         env_set_default(NULL, 0);
151
152         return -EIO;
153 }
154 #endif /* LOADENV */
155
156 U_BOOT_ENV_LOCATION(fat) = {
157         .location       = ENVL_FAT,
158         ENV_NAME("FAT")
159 #ifdef LOADENV
160         .load           = env_fat_load,
161 #endif
162         .save           = ENV_SAVE_PTR(env_fat_save),
163 };