void env_relocate(void){ DEBUGF("%s[%d] offset = 0x%lx\n", __FUNCTION__,__LINE__, gd->reloc_off); #if defined(ENV_IS_EMBEDDED) /* * The environment buffer is embedded with the text segment, * just relocate the environment pointer */ env_ptr = (env_t *)((ulong)env_ptr + gd->reloc_off); DEBUGF("%s[%d] embedded ENV at %p\n", __FUNCTION__,__LINE__,env_ptr); #else /* * We must allocate a buffer for the environment */ env_ptr = (env_t *)malloc(CFG_ENV_SIZE); DEBUGF("%s[%d] malloced ENV at %p\n", __FUNCTION__,__LINE__,env_ptr); #endif /* * After relocation to RAM, we can always use the "memory" functions */ env_get_char = env_get_char_memory; if(gd->env_valid == 0){ #if defined(CFG_ENV_IS_NOWHERE) /* Environment not changable */ //puts("Using default environment\n\n"); #else puts("** Warning: bad env CRC, using default,\n" " use 'saveenv' to save it in flash\n\n"); #endif if(sizeof(default_environment) > ENV_SIZE){ puts("## Error: default environment is too large\n"); return; } memset(env_ptr, 0, sizeof(env_t)); memcpy(env_ptr->data, default_environment, sizeof(default_environment)); #ifdef CFG_REDUNDAND_ENVIRONMENT env_ptr->flags = 0xFF; #endif env_crc_update(); gd->env_valid = 1; } else { env_relocate_spec(); } gd->env_addr = (ulong)&(env_ptr->data); }
void set_default_env(void) { if (sizeof(default_environment) > ENV_SIZE) { puts ("*** Error - default environment is too large\n\n"); return; } memset(env_ptr, 0, sizeof(env_t)); memcpy(env_ptr->data, default_environment, sizeof(default_environment)); #ifdef CONFIG_SYS_REDUNDAND_ENVIRONMENT env_ptr->flags = 0xFF; #endif env_crc_update (); gd->env_valid = 1; }
void default_env(void) { if (sizeof(default_environment) > ENV_SIZE) { puts ("*** Error - default environment is too large\n\n"); return; } memset (env_ptr, 0, sizeof(env_t)); memcpy (env_ptr->data, default_environment, sizeof(default_environment)); #ifdef CFG_ENV_OVERRIDE if (env_override) memcpy(env_ptr->data, env_override, ENV_SIZE); #endif #ifdef CFG_REDUNDAND_ENVIRONMENT env_ptr->flags = 0xFF; #endif env_crc_update (); gd->env_valid = 1; }
void env_relocate (void) { DECLARE_GLOBAL_DATA_PTR; DEBUGF ("%s[%d] offset = 0x%lx\n", __FUNCTION__,__LINE__, gd->reloc_off); #ifdef CONFIG_AMIGAONEG3SE enable_nvram(); #endif #ifdef ENV_IS_EMBEDDED /* * The environment buffer is embedded with the text segment, * just relocate the environment pointer */ env_ptr = (env_t *)((ulong)env_ptr + gd->reloc_off); DEBUGF ("%s[%d] embedded ENV at %p\n", __FUNCTION__,__LINE__,env_ptr); #else /* * We must allocate a buffer for the environment */ env_ptr = (env_t *)malloc (CFG_ENV_SIZE); DEBUGF ("%s[%d] malloced ENV at %p\n", __FUNCTION__,__LINE__,env_ptr); #endif /* * After relocation to RAM, we can always use the "memory" functions */ env_get_char = env_get_char_memory; if (gd->env_valid == 0) { #if defined(CONFIG_GTH) || defined(CFG_ENV_IS_NOWHERE) /* Environment not changable */ puts ("Using default environment\n\n"); #else puts ("*** Warning - bad CRC, using default environment\n\n"); SHOW_BOOT_PROGRESS (-1); #endif if (sizeof(default_environment) > ENV_SIZE) { puts ("*** Error - default environment is too large\n\n"); return; } memset (env_ptr, 0, sizeof(env_t)); memcpy (env_ptr->data, default_environment, sizeof(default_environment)); #ifdef CFG_REDUNDAND_ENVIRONMENT env_ptr->flags = 0xFF; #endif env_crc_update (); gd->env_valid = 1; } else { env_relocate_spec (); } gd->env_addr = (ulong)&(env_ptr->data); #ifdef CONFIG_AMIGAONEG3SE disable_nvram(); #endif }
int _do_setenv (int flag, int argc, char *argv[]) { int i, len, oldval; int console = -1; uchar *env, *nxt = NULL; char *name; bd_t *bd = gd->bd; uchar *env_data = env_get_addr(0); if (!env_data) /* need copy in RAM */ return 1; name = argv[1]; if (strchr(name, '=')) { printf ("## Error: illegal character '=' in variable name \"%s\"\n", name); return 1; } /* * search if variable with this name already exists */ oldval = -1; for (env=env_data; *env; env=nxt+1) { for (nxt=env; *nxt; ++nxt) ; if ((oldval = envmatch((uchar *)name, env-env_data)) >= 0) break; } /* * Delete any existing definition */ if (oldval >= 0) { #ifndef CONFIG_ENV_OVERWRITE /* * Ethernet Address and serial# can be set only once, * ver is readonly. */ if ( #ifdef CONFIG_HAS_UID /* Allow serial# forced overwrite with 0xdeaf4add flag */ ((strcmp (name, "serial#") == 0) && (flag != 0xdeaf4add)) || #else (strcmp (name, "serial#") == 0) || #endif ((strcmp (name, "ethaddr") == 0) #if defined(CONFIG_OVERWRITE_ETHADDR_ONCE) && defined(CONFIG_ETHADDR) && (strcmp ((char *)env_get_addr(oldval),MK_STR(CONFIG_ETHADDR)) != 0) #endif /* CONFIG_OVERWRITE_ETHADDR_ONCE && CONFIG_ETHADDR */ ) ) { printf ("Can't overwrite \"%s\"\n", name); return 1; } #endif /* Check for console redirection */ if (strcmp(name,"stdin") == 0) { console = stdin; } else if (strcmp(name,"stdout") == 0) { console = stdout; } else if (strcmp(name,"stderr") == 0) { console = stderr; } if (console != -1) { if (argc < 3) { /* Cannot delete it! */ printf("Can't delete \"%s\"\n", name); return 1; } #ifdef CONFIG_CONSOLE_MUX i = iomux_doenv(console, argv[2]); if (i) return i; #else /* Try assigning specified device */ if (console_assign (console, argv[2]) < 0) return 1; #ifdef CONFIG_SERIAL_MULTI if (serial_assign (argv[2]) < 0) return 1; #endif #endif /* CONFIG_CONSOLE_MUX */ } /* * Switch to new baudrate if new baudrate is supported */ if (strcmp(argv[1],"baudrate") == 0) { int baudrate = simple_strtoul(argv[2], NULL, 10); int i; for (i=0; i<N_BAUDRATES; ++i) { if (baudrate == baudrate_table[i]) break; } if (i == N_BAUDRATES) { printf ("## Baudrate %d bps not supported\n", baudrate); return 1; } printf ("## Switch baudrate to %d bps and press ENTER ...\n", baudrate); udelay(50000); gd->baudrate = baudrate; #if defined(CONFIG_PPC) || defined(CONFIG_MCF52x2) gd->bd->bi_baudrate = baudrate; #endif serial_setbrg (); udelay(50000); for (;;) { if (getc() == '\r') break; } } if (*++nxt == '\0') { if (env > env_data) { env--; } else { *env = '\0'; } } else { for (;;) { *env = *nxt++; if ((*env == '\0') && (*nxt == '\0')) break; ++env; } } *++env = '\0'; } #ifdef CONFIG_NET_MULTI if (strncmp(name, "eth", 3) == 0) { char *end; int num = simple_strtoul(name+3, &end, 10); if (strcmp(end, "addr") == 0) { eth_set_enetaddr(num, argv[2]); } } #endif /* Delete only ? */ if ((argc < 3) || argv[2] == NULL) { env_crc_update (); return 0; } /* * Append new definition at the end */ for (env=env_data; *env || *(env+1); ++env) ; if (env > env_data) ++env; /* * Overflow when: * "name" + "=" + "val" +"\0\0" > ENV_SIZE - (env-env_data) */ len = strlen(name) + 2; /* add '=' for first arg, ' ' for all others */ for (i=2; i<argc; ++i) { len += strlen(argv[i]) + 1; } if (len > (&env_data[ENV_SIZE]-env)) { printf ("## Error: environment overflow, \"%s\" deleted\n", name); return 1; } while ((*env = *name++) != '\0') env++; for (i=2; i<argc; ++i) { char *val = argv[i]; *env = (i==2) ? '=' : ' '; while ((*++env = *val++) != '\0') ; } /* end is marked with double '\0' */ *++env = '\0'; /* Update CRC */ env_crc_update (); /* * Some variables should be updated when the corresponding * entry in the enviornment is changed */ if (strcmp(argv[1],"ethaddr") == 0) { char *s = argv[2]; /* always use only one arg */ char *e; for (i=0; i<6; ++i) { bd->bi_enetaddr[i] = s ? simple_strtoul(s, &e, 16) : 0; if (s) s = (*e) ? e+1 : e; } #ifdef CONFIG_NET_MULTI eth_set_enetaddr(0, argv[2]); #endif return 0; } if (strcmp(argv[1],"ipaddr") == 0) { char *s = argv[2]; /* always use only one arg */ char *e; unsigned long addr; bd->bi_ip_addr = 0; for (addr=0, i=0; i<4; ++i) { ulong val = s ? simple_strtoul(s, &e, 10) : 0; addr <<= 8; addr |= (val & 0xFF); if (s) s = (*e) ? e+1 : e; } bd->bi_ip_addr = htonl(addr); return 0; } if (strcmp(argv[1],"loadaddr") == 0) { load_addr = simple_strtoul(argv[2], NULL, 16); return 0; } #if defined(CONFIG_CMD_NET) if (strcmp(argv[1],"bootfile") == 0) { copy_filename (BootFile, argv[2], sizeof(BootFile)); return 0; } #endif #ifdef CONFIG_AMIGAONEG3SE if (strcmp(argv[1], "vga_fg_color") == 0 || strcmp(argv[1], "vga_bg_color") == 0 ) { extern void video_set_color(unsigned char attr); extern unsigned char video_get_attr(void); video_set_color(video_get_attr()); return 0; } #endif /* CONFIG_AMIGAONEG3SE */ return 0; }
/************************************************************************ * Set a new environment variable, * or replace or delete an existing one. * * This function will ONLY work with a in-RAM copy of the environment */ int _do_setenv(int flag, int argc, char *argv[]){ int i, len, oldval; int console = -1; uchar *env, *nxt = NULL; char *name; bd_t *bd = gd->bd; uchar *env_data = env_get_addr(0); if(!env_data){ /* need copy in RAM */ return(1); } name = argv[1]; /* * search if variable with this name already exists */ oldval = -1; for(env = env_data; *env; env = nxt + 1){ for(nxt = env; *nxt; ++nxt); if((oldval = envmatch((uchar *)name, env - env_data)) >= 0){ break; } } /* * Delete any existing definition */ if(oldval >= 0){ /* Check for console redirection */ if(strcmp(name, "stdin") == 0){ console = stdin; } else if(strcmp(name, "stdout") == 0){ console = stdout; } else if(strcmp(name, "stderr") == 0){ console = stderr; } if(console != -1){ if(argc < 3){ /* Cannot delete it! */ printf("## Error: can't delete \"%s\"\n", name); return(1); } /* Try assigning specified device */ if(console_assign(console, argv[2]) < 0){ return(1); } #ifdef CONFIG_SERIAL_MULTI if(serial_assign(argv[2]) < 0){ return(1); } #endif } /* * Switch to new baudrate if new baudrate is supported */ if(strcmp(argv[1], "baudrate") == 0){ int baudrate = simple_strtoul(argv[2], NULL, 10); int i; for(i = 0; i < N_BAUDRATES; ++i){ if(baudrate == baudrate_table[i]){ break; } } if(i == N_BAUDRATES){ printf("## Error: baudrate %d bps is not supported,\n", baudrate); printf(" choose one from the list:\n\n"); for(i = 0; i < N_BAUDRATES; ++i){ printf("- %7d bps%s\n", baudrate_table[i], baudrate_table[i] == gd->baudrate ? " [current]" : ""); } printf("\n"); return(1); } printf("Switch baudrate to %d bps and press ENTER...\n", baudrate); udelay(50000); gd->baudrate = baudrate; serial_setbrg(); udelay(50000); for(;;){ if(getc() == '\r'){ break; } } } if(*++nxt == '\0'){ if(env > env_data){ env--; } else { *env = '\0'; } } else { for(;;){ *env = *nxt++; if((*env == '\0') && (*nxt == '\0')){ break; } ++env; } } *++env = '\0'; } #ifdef CONFIG_NET_MULTI if(strncmp(name, "eth", 3) == 0){ char *end; int num = simple_strtoul(name + 3, &end, 10); if(strcmp(end, "addr") == 0){ eth_set_enetaddr(num, argv[2]); } } #endif /* Delete only ? */ if((argc < 3) || argv[2] == NULL){ env_crc_update(); return(0); } /* * Append new definition at the end */ for(env = env_data; *env || *(env + 1); ++env); if(env > env_data){ ++env; } /* * Overflow when: * "name" + "=" + "val" +"\0\0" > ENV_SIZE - (env-env_data) */ len = strlen(name) + 2; /* add '=' for first arg, ' ' for all others */ for(i = 2; i < argc; ++i){ len += strlen(argv[i]) + 1; } if(len > (&env_data[ENV_SIZE] - env)){ printf("## Error: environment overflow, \"%s\" deleted\n", name); return(1); } while((*env = *name++) != '\0'){ env++; } for(i = 2; i < argc; ++i){ char *val = argv[i]; *env = (i == 2) ? '=' : ' '; while((*++env = *val++) != '\0'); } /* end is marked with double '\0' */ *++env = '\0'; /* Update CRC */ env_crc_update(); /* * Some variables should be updated when the corresponding * entry in the enviornment is changed */ if(strcmp(argv[1], "ethaddr") == 0){ char *s = argv[2]; /* always use only one arg */ char *e; for(i = 0; i < 6; ++i){ bd->bi_enetaddr[i] = s ? simple_strtoul(s, &e, 16) : 0; if(s){ s = (*e) ? e + 1 : e; } } #ifdef CONFIG_NET_MULTI eth_set_enetaddr(0, argv[2]); #endif return(0); } if(strcmp(argv[1], "ipaddr") == 0){ char *s = argv[2]; /* always use only one arg */ char *e; unsigned long addr; bd->bi_ip_addr = 0; for(addr = 0, i = 0; i < 4; ++i){ ulong val = s ? simple_strtoul(s, &e, 10) : 0; addr <<= 8; addr |= (val & 0xFF); if(s){ s = (*e) ? e + 1 : e; } } bd->bi_ip_addr = htonl(addr); return(0); } if(strcmp(argv[1], "loadaddr") == 0){ load_addr = simple_strtoul(argv[2], NULL, 16); return(0); } #if (CONFIG_COMMANDS & CFG_CMD_NET) if(strcmp(argv[1], "bootfile") == 0){ copy_filename(BootFile, argv[2], sizeof(BootFile)); return(0); } #endif /* CFG_CMD_NET */ return(0); }
/* ed is not valid anymore! */ return 0; } else { printk(KERN_ERR\ "%s: Cannot find a valid env!\n",\ __func__); return -1; } #ifdef DEBUGME printk(KERN_ERR\ "%s: All done, exiting!\n",\ __func__); #endif /*DEBUGME*/ return 0; } #else /*CONFIG_CIRRUS_DUAL_MTD_ENV*/ int rtcnvet_do_setenv(char *name, char *val) { int len, oldval; unsigned char *env, *nxt = NULL; unsigned char *env_data = NULL; rtcnvet_reload_env(); env_data = (unsigned char *)&env_buf[0]; if (!env_valid) return -1; if (strchr(name, '=')) { printk(KERN_ERR \ "Illegal character '=' in variable name \"%s\"\n", name); return -2; } /* * search if variable with this name already exists */ oldval = -1; for (env = env_data; *env; env = nxt+1) { for (nxt = env; *nxt; ++nxt) ; oldval = envmatch((unsigned char *)name, env-env_data); if (oldval >= 0) break; } /* * Delete any existing definition */ if (oldval >= 0) { if (*++nxt == '\0') if (env > env_data) { env--; } else { *env = '\0'; } else { for (;;) { *env = *nxt++; if ((*env == '\0') && (*nxt == '\0')) break; ++env; } } *++env = '\0'; } /* * Append new definition at the end */ for (env = env_data; *env || *(env+1); ++env) ; if (env > env_data) ++env; /* * Overflow when: * "name" + "=" + "val" +"\0\0" > ENV_SIZE - (env-env_data) */ len = strlen(name) + 2; /* add '=' for first arg, ' ' for all others */ len += strlen(val) + 1; if (len > (&env_data[env_size]-env)) { printk(KERN_ERR \ "Environment overflow, \"%s\" deleted\n", name); return 1; } while ((*env = *name++) != '\0') env++; *env = '='; while ((*++env = *val++) != '\0') ; /* end is marked with double '\0' */ *++env = '\0'; /* Update CRC */ env_crc_update(); /* save every time */ env_save(); return 0; }
/* * The legacy NAND code saved the environment in the first NAND device i.e., * nand_dev_desc + 0. This is also the behaviour using the new NAND code. */ int writeenv(size_t offset, u_char *buf) { struct mtd_info *mtd; struct env_oobinfo_t *env_oobinfo; int error = 0; size_t addr = 0; size_t amount_saved = 0; size_t len; struct mtd_oob_ops aml_oob_ops; unsigned char *data_buf; unsigned char env_oob_buf[sizeof(struct env_oobinfo_t)]; mtd = nand_info[nand_curr_device]; if (mtd == NULL) return 1; struct aml_nand_chip *aml_chip = mtd_to_nand_chip(mtd); data_buf = kzalloc(mtd->writesize, GFP_KERNEL); if (data_buf == NULL) return -ENOMEM; addr = offset; env_oobinfo = (struct env_oobinfo_t *)env_oob_buf; memcpy(env_oobinfo->name, ENV_NAND_MAGIC, 4); env_oobinfo->ec = aml_chip->aml_nandenv_info->env_valid_node->ec; env_oobinfo->timestamp = aml_chip->aml_nandenv_info->env_valid_node->timestamp; env_oobinfo->status_page = 1; while (amount_saved < CONFIG_ENV_SIZE ) { aml_oob_ops.mode = MTD_OOB_AUTO; aml_oob_ops.len = mtd->writesize; aml_oob_ops.ooblen = sizeof(struct env_oobinfo_t); aml_oob_ops.ooboffs = mtd->ecclayout->oobfree[0].offset; aml_oob_ops.datbuf = data_buf; aml_oob_ops.oobbuf = env_oob_buf; memset((unsigned char *)aml_oob_ops.datbuf, 0x0, mtd->writesize); len = min(mtd->writesize, CONFIG_ENV_SIZE - amount_saved); memcpy((unsigned char *)aml_oob_ops.datbuf, buf + amount_saved, len); error = mtd->write_oob(mtd, addr, &aml_oob_ops); if (error) { printf("blk check good but write failed: %llx, %d\n", offset, error); return 1; } addr += mtd->writesize;; amount_saved += mtd->writesize; } if (amount_saved < CONFIG_ENV_SIZE) return 1; kfree(data_buf); return 0; } #ifdef CONFIG_ENV_OFFSET_REDUND int saveenv(void) { struct mtd_info * mtd=get_mtd_device_nm(NAND_NORMAL_NAME); if (IS_ERR(mtd)) return 1; struct aml_nand_chip *aml_chip = mtd_to_nand_chip(mtd); size_t total; size_t offset = CONFIG_ENV_OFFSET; int ret = 0; nand_erase_options_t nand_erase_options; offset = (1024 * aml_chip->page_size * (mtd->writesize / (aml_chip->plane_num * aml_chip->page_size))); if (CONFIG_ENV_OFFSET < offset) _debug ("env define offset must larger than 1024 page size: %d \n", mtd->writesize); else offset = CONFIG_ENV_OFFSET; env_ptr->flags++; total = CONFIG_ENV_SIZE; nand_erase_options.length = CONFIG_ENV_RANGE; nand_erase_options.quiet = 0; nand_erase_options.jffs2 = 0; nand_erase_options.scrub = 0; if (CONFIG_ENV_RANGE < CONFIG_ENV_SIZE) return 1; if(gd->env_valid == 1) { puts ("Erasing redundant Nand...\n"); nand_erase_options.offset = CONFIG_ENV_OFFSET_REDUND; if (nand_erase_opts(mtd, &nand_erase_options)) return 1; puts ("Writing to redundant Nand... "); ret = writeenv(CONFIG_ENV_OFFSET_REDUND, (u_char *) env_ptr); } else { puts ("Erasing Nand...\n"); nand_erase_options.offset = CONFIG_ENV_OFFSET; if (nand_erase_opts(mtd, &nand_erase_options)) return 1; puts ("Writing to Nand... "); ret = writeenv(CONFIG_ENV_OFFSET, (u_char *) env_ptr); } if (ret) { puts("FAILED!\n"); return 1; } puts ("done\n"); gd->env_valid = (gd->env_valid == 2 ? 1 : 2); return ret; } #else /* ! CONFIG_ENV_OFFSET_REDUND */ int saveenv(void) { struct mtd_info *mtd; struct aml_nand_bbt_info *nand_bbt_info; struct env_free_node_t *env_free_node, *env_tmp_node; int error = 0, pages_per_blk, i = 1; size_t addr = 0; struct erase_info aml_env_erase_info; mtd = nand_info[nand_curr_device]; if (mtd == NULL) return 1; struct aml_nand_chip *aml_chip = mtd_to_nand_chip(mtd); if (!aml_chip->aml_nandenv_info->env_init) return 1; pages_per_blk = mtd->erasesize / mtd->writesize; if ((mtd->writesize < CONFIG_ENV_SIZE) && (aml_chip->aml_nandenv_info->env_valid == 1)) i = (CONFIG_ENV_SIZE + mtd->writesize - 1) / mtd->writesize; if (aml_chip->aml_nandenv_info->env_valid) { aml_chip->aml_nandenv_info->env_valid_node->phy_page_addr += i; if ((aml_chip->aml_nandenv_info->env_valid_node->phy_page_addr + i) > pages_per_blk) { env_free_node = kzalloc(sizeof(struct env_free_node_t), GFP_KERNEL); if (env_free_node == NULL) return -ENOMEM; env_free_node->phy_blk_addr = aml_chip->aml_nandenv_info->env_valid_node->phy_blk_addr; env_free_node->ec = aml_chip->aml_nandenv_info->env_valid_node->ec; env_tmp_node = aml_chip->aml_nandenv_info->env_free_node; while (env_tmp_node->next != NULL) { env_tmp_node = env_tmp_node->next; } env_tmp_node->next = env_free_node; env_tmp_node = aml_chip->aml_nandenv_info->env_free_node; aml_chip->aml_nandenv_info->env_valid_node->phy_blk_addr = env_tmp_node->phy_blk_addr; aml_chip->aml_nandenv_info->env_valid_node->phy_page_addr = 0; aml_chip->aml_nandenv_info->env_valid_node->ec = env_tmp_node->ec; aml_chip->aml_nandenv_info->env_valid_node->timestamp += 1; aml_chip->aml_nandenv_info->env_free_node = env_tmp_node->next; kfree(env_tmp_node); } } else { env_tmp_node = aml_chip->aml_nandenv_info->env_free_node; aml_chip->aml_nandenv_info->env_valid_node->phy_blk_addr = env_tmp_node->phy_blk_addr; aml_chip->aml_nandenv_info->env_valid_node->phy_page_addr = 0; aml_chip->aml_nandenv_info->env_valid_node->ec = env_tmp_node->ec; aml_chip->aml_nandenv_info->env_valid_node->timestamp += 1; aml_chip->aml_nandenv_info->env_free_node = env_tmp_node->next; kfree(env_tmp_node); } addr = aml_chip->aml_nandenv_info->env_valid_node->phy_blk_addr; addr *= mtd->erasesize; addr += aml_chip->aml_nandenv_info->env_valid_node->phy_page_addr * mtd->writesize; if (aml_chip->aml_nandenv_info->env_valid_node->phy_page_addr == 0) { memset(&aml_env_erase_info, 0, sizeof(struct erase_info)); aml_env_erase_info.mtd = mtd; aml_env_erase_info.addr = addr; aml_env_erase_info.len = mtd->erasesize; error = mtd->erase(mtd, &aml_env_erase_info); if (error) { printf("env free blk erase failed %d\n", error); mtd->block_markbad(mtd, addr); return error; } aml_chip->aml_nandenv_info->env_valid_node->ec++; } nand_bbt_info = &aml_chip->aml_nandenv_info->nand_bbt_info; if ((!memcmp(nand_bbt_info->bbt_head_magic, BBT_HEAD_MAGIC, 4)) && (!memcmp(nand_bbt_info->bbt_tail_magic, BBT_TAIL_MAGIC, 4))) { memcpy(env_ptr->data + default_environment_size, aml_chip->aml_nandenv_info->nand_bbt_info.bbt_head_magic, sizeof(struct aml_nand_bbt_info)); env_crc_update (); } printf("Writing to Nand... \n"); if (writeenv(addr, (u_char *) env_ptr)) { printf("FAILED!\n"); return 1; } printf("Successful!\n"); return error; }
int saveenv(void) { env_t env_new; ssize_t len; char *saved_data = NULL; char *res; int rc = 1; char flag = OBSOLETE_FLAG, new_flag = ACTIVE_FLAG; #if CONFIG_ENV_SECT_SIZE > CONFIG_ENV_SIZE ulong up_data = 0; #endif debug("Protect off %08lX ... %08lX\n", (ulong)flash_addr, end_addr); if (flash_sect_protect(0, (ulong)flash_addr, end_addr)) { goto done; } debug("Protect off %08lX ... %08lX\n", (ulong)flash_addr_new, end_addr_new); if (flash_sect_protect(0, (ulong)flash_addr_new, end_addr_new)) { goto done; } res = (char *)&env_new.data; len = hexport_r(&env_htab, '\0', &res, ENV_SIZE); if (len < 0) { error("Cannot export environment: errno = %d\n", errno); goto done; } env_new.crc = crc32(0, env_new.data, ENV_SIZE); env_new.flags = new_flag; env_crc_update(); #if CONFIG_ENV_SECT_SIZE > CONFIG_ENV_SIZE up_data = (end_addr_new + 1 - ((long)flash_addr_new + CONFIG_ENV_SIZE)); debug("Data to save 0x%lX\n", up_data); if (up_data) { if ((saved_data = malloc(up_data)) == NULL) { printf("Unable to save the rest of sector (%ld)\n", up_data); goto done; } memcpy(saved_data, (void *)((long)flash_addr_new + CONFIG_ENV_SIZE), up_data); debug("Data (start 0x%lX, len 0x%lX) saved at 0x%p\n", (long)flash_addr_new + CONFIG_ENV_SIZE, up_data, saved_data); } #endif puts("Erasing Flash..."); debug(" %08lX ... %08lX ...", (ulong)flash_addr_new, end_addr_new); if (flash_sect_erase((ulong)flash_addr_new, end_addr_new)) { goto done; } puts("Writing to Flash... "); debug(" %08lX ... %08lX ...", (ulong)&(flash_addr_new->data), sizeof(env_ptr->data)+(ulong)&(flash_addr_new->data)); if ((rc = flash_write((char *)&env_new, (ulong)flash_addr_new, sizeof(env_new))) || (rc = flash_write(&flag, (ulong)&(flash_addr->flags), sizeof(flash_addr->flags))) ) { flash_perror(rc); goto done; } #if CONFIG_ENV_SECT_SIZE > CONFIG_ENV_SIZE if (up_data) { /* restore the rest of sector */ debug("Restoring the rest of data to 0x%lX len 0x%lX\n", (long)flash_addr_new + CONFIG_ENV_SIZE, up_data); if (flash_write(saved_data, (long)flash_addr_new + CONFIG_ENV_SIZE, up_data)) { flash_perror(rc); goto done; } } #endif puts("done\n"); { env_t * etmp = flash_addr; ulong ltmp = end_addr; flash_addr = flash_addr_new; flash_addr_new = etmp; end_addr = end_addr_new; end_addr_new = ltmp; } rc = 0; done: if (saved_data) free(saved_data); /* try to re-protect */ (void) flash_sect_protect(1, (ulong)flash_addr, end_addr); (void) flash_sect_protect(1, (ulong)flash_addr_new, end_addr_new); return rc; }