"Das U-Boot" Source Tree
at master 179 lines 4.2 kB view raw
1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * (C) Copyright 2000-2010 4 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. 5 * 6 * (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH <www.elinos.com> 7 * Andreas Heppel <aheppel@sysgo.de> 8 */ 9 10#include <command.h> 11#include <eeprom.h> 12#include <env.h> 13#include <env_internal.h> 14#include <asm/global_data.h> 15#include <linux/stddef.h> 16#include <u-boot/crc.h> 17#include <search.h> 18#include <errno.h> 19#include <linux/compiler.h> /* for BUG_ON */ 20 21DECLARE_GLOBAL_DATA_PTR; 22 23static int env_eeprom_load(void) 24{ 25 char buf_env[CONFIG_ENV_SIZE]; 26 unsigned int off = CONFIG_ENV_OFFSET; 27 28#ifdef CONFIG_ENV_OFFSET_REDUND 29 ulong len, crc[2], crc_tmp; 30 unsigned int off_env[2]; 31 uchar rdbuf[64], flags[2]; 32 int i, crc_ok[2] = {0, 0}; 33 34 eeprom_init(-1); /* prepare for EEPROM read/write */ 35 36 off_env[0] = CONFIG_ENV_OFFSET; 37 off_env[1] = CONFIG_ENV_OFFSET_REDUND; 38 39 for (i = 0; i < 2; i++) { 40 /* read CRC */ 41 eeprom_read(CONFIG_SYS_I2C_EEPROM_ADDR, 42 off_env[i] + offsetof(env_t, crc), 43 (uchar *)&crc[i], sizeof(ulong)); 44 /* read FLAGS */ 45 eeprom_read(CONFIG_SYS_I2C_EEPROM_ADDR, 46 off_env[i] + offsetof(env_t, flags), 47 (uchar *)&flags[i], sizeof(uchar)); 48 49 crc_tmp = 0; 50 len = ENV_SIZE; 51 off = off_env[i] + offsetof(env_t, data); 52 while (len > 0) { 53 int n = (len > sizeof(rdbuf)) ? sizeof(rdbuf) : len; 54 55 eeprom_read(CONFIG_SYS_I2C_EEPROM_ADDR, off, 56 rdbuf, n); 57 58 crc_tmp = crc32(crc_tmp, rdbuf, n); 59 len -= n; 60 off += n; 61 } 62 63 if (crc_tmp == crc[i]) 64 crc_ok[i] = 1; 65 } 66 67 if (!crc_ok[0] && !crc_ok[1]) { 68 gd->env_addr = 0; 69 gd->env_valid = ENV_INVALID; 70 } else if (crc_ok[0] && !crc_ok[1]) { 71 gd->env_valid = ENV_VALID; 72 } else if (!crc_ok[0] && crc_ok[1]) { 73 gd->env_valid = ENV_REDUND; 74 } else { 75 /* both ok - check serial */ 76 if (flags[0] == ENV_REDUND_ACTIVE && 77 flags[1] == ENV_REDUND_OBSOLETE) 78 gd->env_valid = ENV_VALID; 79 else if (flags[0] == ENV_REDUND_OBSOLETE && 80 flags[1] == ENV_REDUND_ACTIVE) 81 gd->env_valid = ENV_REDUND; 82 else if (flags[0] == 0xFF && flags[1] == 0) 83 gd->env_valid = ENV_REDUND; 84 else if (flags[1] == 0xFF && flags[0] == 0) 85 gd->env_valid = ENV_VALID; 86 else /* flags are equal - almost impossible */ 87 gd->env_valid = ENV_VALID; 88 } 89 90#else /* CONFIG_ENV_OFFSET_REDUND */ 91 ulong crc, len, new; 92 uchar rdbuf[64]; 93 94 eeprom_init(-1); /* prepare for EEPROM read/write */ 95 96 /* read old CRC */ 97 eeprom_read(CONFIG_SYS_I2C_EEPROM_ADDR, 98 CONFIG_ENV_OFFSET + offsetof(env_t, crc), 99 (uchar *)&crc, sizeof(ulong)); 100 101 new = 0; 102 len = ENV_SIZE; 103 off = offsetof(env_t, data); 104 while (len > 0) { 105 int n = (len > sizeof(rdbuf)) ? sizeof(rdbuf) : len; 106 107 eeprom_read(CONFIG_SYS_I2C_EEPROM_ADDR, 108 CONFIG_ENV_OFFSET + off, rdbuf, n); 109 new = crc32(new, rdbuf, n); 110 len -= n; 111 off += n; 112 } 113 114 if (crc == new) { 115 gd->env_valid = ENV_VALID; 116 } else { 117 gd->env_valid = ENV_INVALID; 118 } 119#endif /* CONFIG_ENV_OFFSET_REDUND */ 120 121 off = CONFIG_ENV_OFFSET; 122#ifdef CONFIG_ENV_OFFSET_REDUND 123 if (gd->env_valid == ENV_REDUND) 124 off = CONFIG_ENV_OFFSET_REDUND; 125#endif 126 127 eeprom_read(CONFIG_SYS_I2C_EEPROM_ADDR, 128 off, (uchar *)buf_env, CONFIG_ENV_SIZE); 129 130 return env_import(buf_env, 1, H_EXTERNAL); 131} 132 133static int env_eeprom_save(void) 134{ 135 env_t env_new; 136 int rc; 137 unsigned int off = CONFIG_ENV_OFFSET; 138#ifdef CONFIG_ENV_OFFSET_REDUND 139 unsigned int off_red = CONFIG_ENV_OFFSET_REDUND; 140 char flag_obsolete = ENV_REDUND_OBSOLETE; 141#endif 142 143 rc = env_export(&env_new); 144 if (rc) 145 return rc; 146 147#ifdef CONFIG_ENV_OFFSET_REDUND 148 if (gd->env_valid == ENV_VALID) { 149 off = CONFIG_ENV_OFFSET_REDUND; 150 off_red = CONFIG_ENV_OFFSET; 151 } 152 153 env_new.flags = ENV_REDUND_ACTIVE; 154#endif 155 156 rc = eeprom_write(CONFIG_SYS_I2C_EEPROM_ADDR, 157 off, (uchar *)&env_new, CONFIG_ENV_SIZE); 158 159#ifdef CONFIG_ENV_OFFSET_REDUND 160 if (rc == 0) { 161 eeprom_write(CONFIG_SYS_I2C_EEPROM_ADDR, 162 off_red + offsetof(env_t, flags), 163 (uchar *)&flag_obsolete, 1); 164 165 if (gd->env_valid == ENV_VALID) 166 gd->env_valid = ENV_REDUND; 167 else 168 gd->env_valid = ENV_VALID; 169 } 170#endif 171 return rc; 172} 173 174U_BOOT_ENV_LOCATION(eeprom) = { 175 .location = ENVL_EEPROM, 176 ENV_NAME("EEPROM") 177 .load = env_eeprom_load, 178 .save = env_save_ptr(env_eeprom_save), 179};