uboot/env/fat.c
<<
>>
Prefs
   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 <asm/global_data.h>
  22#include <linux/stddef.h>
  23
  24#ifdef CONFIG_SPL_BUILD
  25/* TODO(sjg@chromium.org): Figure out why this is needed */
  26# if !defined(CONFIG_TARGET_AM335X_EVM) || defined(CONFIG_SPL_OS_BOOT)
  27#  define LOADENV
  28# endif
  29#else
  30# define LOADENV
  31#endif
  32
  33DECLARE_GLOBAL_DATA_PTR;
  34
  35static char *env_fat_device_and_part(void)
  36{
  37#ifdef CONFIG_MMC
  38        static char *part_str;
  39
  40        if (!part_str) {
  41                part_str = CONFIG_ENV_FAT_DEVICE_AND_PART;
  42                if (!strcmp(CONFIG_ENV_FAT_INTERFACE, "mmc") && part_str[0] == ':') {
  43                        part_str = "0" CONFIG_ENV_FAT_DEVICE_AND_PART;
  44                        part_str[0] += mmc_get_env_dev();
  45                }
  46        }
  47
  48        return part_str;
  49#else
  50        return CONFIG_ENV_FAT_DEVICE_AND_PART;
  51#endif
  52}
  53
  54static int env_fat_save(void)
  55{
  56        env_t __aligned(ARCH_DMA_MINALIGN) env_new;
  57        struct blk_desc *dev_desc = NULL;
  58        struct disk_partition info;
  59        const char *file = CONFIG_ENV_FAT_FILE;
  60        int dev, part;
  61        int err;
  62        loff_t size;
  63
  64        err = env_export(&env_new);
  65        if (err)
  66                return err;
  67
  68        part = blk_get_device_part_str(CONFIG_ENV_FAT_INTERFACE,
  69                                        env_fat_device_and_part(),
  70                                        &dev_desc, &info, 1);
  71        if (part < 0)
  72                return 1;
  73
  74        dev = dev_desc->devnum;
  75        if (fat_set_blk_dev(dev_desc, &info) != 0) {
  76                /*
  77                 * This printf is embedded in the messages from env_save that
  78                 * will calling it. The missing \n is intentional.
  79                 */
  80                printf("Unable to use %s %d:%d... \n",
  81                       CONFIG_ENV_FAT_INTERFACE, dev, part);
  82                return 1;
  83        }
  84
  85#ifdef CONFIG_SYS_REDUNDAND_ENVIRONMENT
  86        if (gd->env_valid == ENV_VALID)
  87                file = CONFIG_ENV_FAT_FILE_REDUND;
  88#endif
  89
  90        err = file_fat_write(file, (void *)&env_new, 0, sizeof(env_t), &size);
  91        if (err == -1) {
  92                /*
  93                 * This printf is embedded in the messages from env_save that
  94                 * will calling it. The missing \n is intentional.
  95                 */
  96                printf("Unable to write \"%s\" from %s%d:%d... \n",
  97                        file, CONFIG_ENV_FAT_INTERFACE, dev, part);
  98                return 1;
  99        }
 100
 101#ifdef CONFIG_SYS_REDUNDAND_ENVIRONMENT
 102        gd->env_valid = (gd->env_valid == ENV_REDUND) ? ENV_VALID : ENV_REDUND;
 103#endif
 104
 105        return 0;
 106}
 107
 108#ifdef LOADENV
 109static int env_fat_load(void)
 110{
 111        ALLOC_CACHE_ALIGN_BUFFER(char, buf1, CONFIG_ENV_SIZE);
 112#ifdef CONFIG_SYS_REDUNDAND_ENVIRONMENT
 113        ALLOC_CACHE_ALIGN_BUFFER(char, buf2, CONFIG_ENV_SIZE);
 114        int err2;
 115#endif
 116        struct blk_desc *dev_desc = NULL;
 117        struct disk_partition info;
 118        int dev, part;
 119        int err1;
 120
 121#ifdef CONFIG_MMC
 122        if (!strcmp(CONFIG_ENV_FAT_INTERFACE, "mmc"))
 123                mmc_initialize(NULL);
 124#endif
 125
 126        part = blk_get_device_part_str(CONFIG_ENV_FAT_INTERFACE,
 127                                        env_fat_device_and_part(),
 128                                        &dev_desc, &info, 1);
 129        if (part < 0)
 130                goto err_env_relocate;
 131
 132        dev = dev_desc->devnum;
 133        if (fat_set_blk_dev(dev_desc, &info) != 0) {
 134                /*
 135                 * This printf is embedded in the messages from env_save that
 136                 * will calling it. The missing \n is intentional.
 137                 */
 138                printf("Unable to use %s %d:%d... \n",
 139                       CONFIG_ENV_FAT_INTERFACE, dev, part);
 140                goto err_env_relocate;
 141        }
 142
 143        err1 = file_fat_read(CONFIG_ENV_FAT_FILE, buf1, CONFIG_ENV_SIZE);
 144#ifdef CONFIG_SYS_REDUNDAND_ENVIRONMENT
 145        err2 = file_fat_read(CONFIG_ENV_FAT_FILE_REDUND, buf2, CONFIG_ENV_SIZE);
 146
 147        err1 = (err1 >= 0) ? 0 : -1;
 148        err2 = (err2 >= 0) ? 0 : -1;
 149        return env_import_redund(buf1, err1, buf2, err2, H_EXTERNAL);
 150#else
 151        if (err1 < 0) {
 152                /*
 153                 * This printf is embedded in the messages from env_save that
 154                 * will calling it. The missing \n is intentional.
 155                 */
 156                printf("Unable to read \"%s\" from %s%d:%d... \n",
 157                        CONFIG_ENV_FAT_FILE, CONFIG_ENV_FAT_INTERFACE, dev, part);
 158                goto err_env_relocate;
 159        }
 160
 161        return env_import(buf1, 1, H_EXTERNAL);
 162#endif
 163
 164err_env_relocate:
 165        env_set_default(NULL, 0);
 166
 167        return -EIO;
 168}
 169#endif /* LOADENV */
 170
 171U_BOOT_ENV_LOCATION(fat) = {
 172        .location       = ENVL_FAT,
 173        ENV_NAME("FAT")
 174#ifdef LOADENV
 175        .load           = env_fat_load,
 176#endif
 177        .save           = ENV_SAVE_PTR(env_fat_save),
 178};
 179