1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * (c) Copyright 2016 by VRT Technology 4 * 5 * Author: 6 * Stuart Longland <stuartl@vrt.com.au> 7 * 8 * Based on FAT environment driver 9 * (c) Copyright 2011 by Tigris Elektronik GmbH 10 * 11 * Author: 12 * Maximilian Schwerin <mvs@tigris.de> 13 * 14 * and EXT4 filesystem implementation 15 * (C) Copyright 2011 - 2012 Samsung Electronics 16 * EXT4 filesystem implementation in Uboot by 17 * Uma Shankar <uma.shankar@samsung.com> 18 * Manjunatha C Achar <a.manjunatha@samsung.com> 19 */ 20 21#include <common.h> 22#include <part.h> 23 24#include <command.h> 25#include <env.h> 26#include <env_internal.h> 27#include <linux/stddef.h> 28#include <malloc.h> 29#include <memalign.h> 30#include <search.h> 31#include <errno.h> 32#include <ext4fs.h> 33#include <mmc.h> 34#include <scsi.h> 35#include <virtio.h> 36#include <asm/global_data.h> 37 38DECLARE_GLOBAL_DATA_PTR; 39 40__weak const char *env_ext4_get_intf(void) 41{ 42 return (const char *)CONFIG_ENV_EXT4_INTERFACE; 43} 44 45__weak const char *env_ext4_get_dev_part(void) 46{ 47#ifdef CONFIG_MMC 48 static char *part_str; 49 50 if (!part_str) { 51 part_str = CONFIG_ENV_EXT4_DEVICE_AND_PART; 52 if (!strcmp(CONFIG_ENV_EXT4_INTERFACE, "mmc") && part_str[0] == ':') { 53 part_str = "0" CONFIG_ENV_EXT4_DEVICE_AND_PART; 54 part_str[0] += mmc_get_env_dev(); 55 } 56 } 57 58 return part_str; 59#else 60 return (const char *)CONFIG_ENV_EXT4_DEVICE_AND_PART; 61#endif 62} 63 64static int env_ext4_save_buffer(env_t *env_new) 65{ 66 struct blk_desc *dev_desc = NULL; 67 struct disk_partition info; 68 int dev, part; 69 int err; 70 const char *ifname = env_ext4_get_intf(); 71 const char *dev_and_part = env_ext4_get_dev_part(); 72 73 part = blk_get_device_part_str(ifname, dev_and_part, 74 &dev_desc, &info, 1); 75 if (part < 0) 76 return 1; 77 78 dev = dev_desc->devnum; 79 ext4fs_set_blk_dev(dev_desc, &info); 80 81 if (!ext4fs_mount()) { 82 printf("\n** Unable to use %s %s for saveenv **\n", 83 ifname, dev_and_part); 84 return 1; 85 } 86 87 err = ext4fs_write(CONFIG_ENV_EXT4_FILE, (void *)env_new, 88 sizeof(env_t), FILETYPE_REG); 89 ext4fs_close(); 90 91 if (err == -1) { 92 printf("\n** Unable to write \"%s\" from %s%d:%d **\n", 93 CONFIG_ENV_EXT4_FILE, ifname, dev, part); 94 return 1; 95 } 96 97 return 0; 98} 99 100static int env_ext4_save(void) 101{ 102 env_t env_new; 103 int err; 104 105 err = env_export(&env_new); 106 if (err) 107 return err; 108 109 err = env_ext4_save_buffer(&env_new); 110 if (err) 111 return err; 112 113 gd->env_valid = ENV_VALID; 114 puts("done\n"); 115 116 return 0; 117} 118 119static int env_ext4_erase(void) 120{ 121 env_t env_new; 122 int err; 123 124 memset(&env_new, 0, sizeof(env_t)); 125 126 err = env_ext4_save_buffer(&env_new); 127 if (err) 128 return err; 129 130 gd->env_valid = ENV_INVALID; 131 puts("done\n"); 132 133 return 0; 134} 135 136static int env_ext4_load(void) 137{ 138 ALLOC_CACHE_ALIGN_BUFFER(char, buf, CONFIG_ENV_SIZE); 139 struct blk_desc *dev_desc = NULL; 140 struct disk_partition info; 141 int dev, part; 142 int err; 143 loff_t off; 144 const char *ifname = env_ext4_get_intf(); 145 const char *dev_and_part = env_ext4_get_dev_part(); 146 147#ifdef CONFIG_MMC 148 if (!strcmp(ifname, "mmc")) 149 mmc_initialize(NULL); 150#endif 151#if defined(CONFIG_AHCI) || defined(CONFIG_SCSI) 152 if (!strcmp(ifname, "scsi")) 153 scsi_scan(true); 154#endif 155#if defined(CONFIG_VIRTIO) 156 if (!strcmp(ifname, "virtio")) 157 virtio_init(); 158#endif 159 160 part = blk_get_device_part_str(ifname, dev_and_part, 161 &dev_desc, &info, 1); 162 if (part < 0) 163 goto err_env_relocate; 164 165 dev = dev_desc->devnum; 166 ext4fs_set_blk_dev(dev_desc, &info); 167 168 if (!ext4fs_mount()) { 169 printf("\n** Unable to use %s %s for loading the env **\n", 170 ifname, dev_and_part); 171 goto err_env_relocate; 172 } 173 174 err = ext4_read_file(CONFIG_ENV_EXT4_FILE, buf, 0, CONFIG_ENV_SIZE, 175 &off); 176 ext4fs_close(); 177 178 if (err == -1) { 179 printf("\n** Unable to read \"%s\" from %s%d:%d **\n", 180 CONFIG_ENV_EXT4_FILE, ifname, dev, part); 181 goto err_env_relocate; 182 } 183 184 err = env_import(buf, 1, H_EXTERNAL); 185 if (!err) 186 gd->env_valid = ENV_VALID; 187 188 return err; 189 190err_env_relocate: 191 env_set_default(NULL, 0); 192 193 return -EIO; 194} 195 196U_BOOT_ENV_LOCATION(ext4) = { 197 .location = ENVL_EXT4, 198 ENV_NAME("EXT4") 199 .load = env_ext4_load, 200 .save = ENV_SAVE_PTR(env_ext4_save), 201 .erase = ENV_ERASE_PTR(env_ext4_erase), 202}; 203