Mpc8313erdb Code Analysis of Uboot environment variables read from NAND flash in Linux
[Email protected]
One. Story cause
Because the file system has grown, it has greatly exceeded the 8MB nor FLASH, and has had to save the kernel, file system and device tree files to NAND flash. But because of the use of RAMDisk, and can not save some individual configuration and parameters, the simplest need is to set the system's IP,,,
To use the unified RAMDisk, and the implementation of the Linux startup, set to the parameters of the function, it is convenient to pass these parameters from the Uboot passed, this has been the certification of everyone, we can directly add the startup parameters, and then read out in the kernel, this method of comparison method, The only downside is the need to modify the kernel,,,
In addition, the corresponding parameters in the form of Uboot environment variables written to NAND flash, and then read out in Linux, this method is better, do not modify the kernel, do not modify the Ltib inside the standard package can be completed ...
In fact, uboot inside the code with Linux read and write environment variables, in uboot/tools/env This directory, of course, you can also directly use: "Make env" to compile, in the same directory will generate fw_printenv this executable file, and then, Need to modify the configuration Fw_env.config, and then put it in your file system: "/etc/fw_env.config", and then build two soft links on it,,,
This process is more complex, I use the u-boot-1.3.0 code, the result of making env is wrong, you can try to compile a look, if you can pass at once can not debug ~
In fact, under Linux read the uboot inside the environment variable method, very simple. is basic file reading, and string parsing, mainly to figure out where your NAND flash environment variables are stored.
Here is a small example of what I wrote according to Fw_printenv, which can be compiled directly and then read the environment variables inside NAND ...
Two. Implementation of the specific 1. Determine where Uboot environment parameters are saved in Flash
Because I use MPC8313ERDB this board, so look at the Uboot code "include/configs/mpc8313erdb.h" This definition file has the following definition:
#define Cfg_nand_block_size (<<)/ * NAND chip BLOCK SIZE *//* * Environment */#if defined (config_nand_ U_boot) #define Cfg_env_is_in_nand1#define cfg_env_sizecfg_nand_block_size#define Cfg_env_offset ((1024<<10)- (cfg_nand_block_size<<1)) #elif!defined (cfg_ramboot) #define Cfg_env_is_in_flash1#define cfg_env_addr (cfg_monitor_base + 0x40000) #define Cfg_ env_sect_size0x10000/* 64K (one sector) for ENV */#define CFG_ENV_SIZE0X2000
Because I'm using NAND UBOOT here, it should be the previous one:
Cfg_env_size = 16<<10 = 0x4000 = 16k
Cfg_env_offset = (1024<<10)-(0x4000<<1) = 0xf8000
In the same way, you can also see the definition in the Include/configs directory, depending on what board you are using.
2. Read the Uboot MTD file
Determined the environment variable in the flash offset, you can directly open the Uboot MTD device file, and then use Lseek to locate, and then use the Read function to read the UBOOT environment variables.
So here, Uboot exactly is which MTD device is different from your device tree file, of course, you can also run directly under Linux command "CAT/PROC/MTD" inside to check.
3. CRC check
How is it correct to be sure that the data is read? In fact, at the beginning of the UBOOT environment variable, there is a 4 byte 32-bit CRC check, we can check,,,
This CRC takes the Uboot code directly.
Crc32.h file, this is just a declaration of a CRC32 function
#ifndef_CRC32_H # define _crc32_h/* */unsigned long crc32 (unsigned long, const unsigned char *, unsigned int); #endif
CRC32.C file, the implementation of the CRC32 function:
/* * This file was derived from crc32.c from the zlib-1.1.3 distribution * by Jean-loup gailly and Mark Adler. *//* crc32.c--compute the CRC-32 of a data stream * Copyright (c) 1995-1998 Mark Adler * for conditions of distribution and use, see Copyright notice in zlib.h *//* ======================================================================== * Table of CRC-32 ' s of single-byte values (made by make_crc_table) */static const unsigned long crc_table[256] = {0x00 000000L, 0x77073096l, 0xee0e612cl, 0x990951bal, 0x076dc419l, 0X706AF48FL, 0xe963a535l, 0x9e6495a3l, 0x0edb8832L, 0x79dcb8a4l, 0xe0d5e91el, 0x97d2d988l, 0X09B64C2BL, 0X7EB17CBDL, 0xe7b82d07l, 0x90bf1d91l, 0x1db71064L, 0x6ab020f2L, 0x f3b97148l, 0x84be41del, 0X1ADAD47DL, 0x6ddde4ebl, 0xf4d4b551l, 0x83d385c7l, 0x136c9856l, 0x646ba8c0L, 0xfd62f97aL, 0x8a 65c9ecl, 0X14015C4FL, 0x63066cd9l, 0xfa0f3d63l, 0x8d080df5l, 0x3b6e20c8l, 0x4c69105el, 0xd56041e4l, 0xa2677172L, 0X3C03 e4d1l, 0x4b04d447l, 0XD20D85FDL, 0XA50AB56BL, 0x35b5a8fal, 0X42B2986CL, 0xdbbbc9d6l, 0xacbcf940l, 0x32d86ce3l, 0x45df5c75l, 0XDCD60DCFL, 0xabd13d59L, 0x26d930acL, 0x51de003al, 0xc8d75180l, 0xbfd06116l, 0x21b4f4b5l, 0x56b3c423l, 0xcfba9599l, 0XB8BDA50FL, 0x2802b89eL, 0x5f058808L, 0x C60CD9B2L, 0xb10be924l, 0x2f6f7c87l, 0x58684c11l, 0xc1611dabl, 0xb6662d3dl, 0x76dc4190l, 0x01db7106L, 0x98d220bcL, 0xEF D5102al, 0x71b18589l, 0X06B6B51FL, 0x9fbfe4a5l, 0xe8b8d433l, 0x7807c9a2l, 0x0f00f934l, 0x9609a88el, 0xe10e9818L, 0x7f6a 0dbbL, 0X086D3D2DL, 0x91646c97l, 0xe6635c01l, 0x6b6b51f4l, 0x1c6c6162l, 0x856530d8l, 0xf262004el, 0x6c0695edL, 0x1b01a5 7bL, 0x8208f4c1l, 0xf50fc457l, 0x65b0d9c6l, 0x12b7e950l, 0x8bbeb8eal, 0XFCB9887CL, 0X62DD1DDFL, 0x15da2d49L, 0X8CD37CF3L, 0xfbd44c65l, 0x4db26158l, 0x3ab551cel, 0xa3bc0074l, 0xd4bb30e2l, 0x4adfa541l, 0x3dd895d7L, 0xa4d1c46dL, 0x D3D6F4FBL, 0x4369e96al, 0X346ED9FCL, 0xad678846l, 0xda60b8d0l, 0x44042d73l, 0x33031de5l, 0xaa0a4c5fL, 0xdd0d7cc9L, 0x50 05713cL, 0x270241aal, 0xbe0b1010l, 0xc90c2086l, 0x5768b525l, 0x206f85b3l, 0xb966d409l, 0XCE61E49FL, 0x5edef90el, 0x29d9c998l, 0xb0d09822l, 0xc7d7a8b4L, 0x59b33d17L, 0x 2eb40d81l, 0XB7BD5C3BL, 0xc0ba6cadl, 0xedb88320l, 0x9abfb3b6l, 0x03b6e20cl, 0x74b1d29al, 0xead54739L, 0x9dd277afL, 0x04db2615l, 0x73dc1683l, 0xe3630b12l, 0x94643b84l, 0x0d6d6a3el, 0x7a6a5aa8l, 0XE40ECF0BL, 0x9309ff9dL, 0x0a00ae27L, 0x 7d079eb1l, 0xf00f9344l, 0x8708a3d2l, 0x1e01f268l, 0x6906c2fel, 0XF762575DL, 0X806567CBL, 0x196c3671L, 0x6e6b06e7L, 0xFE d41b76l, 0x89d32be0l, 0x10da7a5al, 0X67DD4ACCL, 0XF9B9DF6FL, 0x8ebeeff9l, 0x17b7be43l, 0x60b08ed5l, 0xd6d6a3e8L, 0XA1D1 937eL, 0x38d8c2c4l, 0x4fdff252l, 0xd1bb67f1l, 0xa6bc5767l, 0x3fb506ddl, 0X48B2364BL, 0xd80d2bdal, 0xaf0a1b4cL, 0x36034a F6L, 0x41047a60l, 0xdf60efc3l, 0xa867df55l, 0X316E8EEFL, 0x4669be79l, 0XCB61B38CL, 0xbc66831al, 0x256fd2a0L, 0x5268e236l, 0xcc0c7795l, 0xbb0b4703l, 0x220216b9l, 0X5505262FL, 0xc5ba3bbel, 0xb2bd0b28l, 0x2bb45a92L, 0x5cb36a04L, 0x C2D7FFA7L, 0xb5d0cf31l, 0X2CD99E8BL, 0X5BDEAE1DL, 0x9b64c2b0l, 0xec63f226l, 0X756AA39CL, 0x026d930al, 0x9c0906a9l, 0XEB0E363FL, 0x72076785l, 0x05005713L, 0x95bf4a82L , 0xe2b87a14l, 0x7bb12bael, 0x0cb61b38l, 0X92D28E9BL, 0xe5d5be0dl, 0x7cdcefb7l, 0x0bdbdf21l, 0x86d3d2d4L, 0xf1d4e242L, 0 x68ddb3f8l, 0x1fda836el, 0X81BE16CDL, 0XF6B9265BL, 0x6fb077e1l, 0x18b74777l, 0x88085ae6l, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cl, 0X8F659EFFL, 0xf862ae69l, 0x616bffd3l, 0x166ccf45l, 0xa00ae278l, 0xd70dd2eel, 0x4e048354L, 0x3903b3c2L, 0x a7672661l, 0xd06016f7l, 0X4969474DL, 0x3e6e77dbl, 0xaed16a4al, 0XD9D65ADCL, 0x40df0b66l, 0x37d83bf0L, 0xa9bcae53L, 0xde bb9ec5l, 0X47B2CF7FL, 0x30b5ffe9l, 0XBDBDF21CL, 0xcabac28al, 0x53b39330l, 0x24b4a3a6l, 0xbad03605l, 0xcdd70693L, 0X54DE 5729L, 0X23D967BFL, 0xb3667a2el, 0xc4614ab8l, 0x5d681b02l, 0x2a6f2b94l, 0xb40bbe37l, 0xc30c8ea1l, 0x5a05df1bL, 0x2d02ef 8dL}; #define DO1 (BUF) CRC = Crc_table[((int) CRC ^ (*buf++)) & 0xFF] ^ (CRC >> 8); #define DO2 (BUF) DO1 (BUF); DO1 (BUF), #define DO4 (BUF) DO2 (BUF);DO2 (BUF), #define DO8 (BUF) DO4 (BUF); DO4 (BUF);/* ========================================================================= */unsigned long CRC32 ( unsigned int crc,const unsigned char *buf, unsigned int len) {CRC = CRC ^ 0xffffffffL; while (Len >= 8) {DO8 (BUF); Len-= 8; } if (len) do {DO1 (BUF); } while (--len); return CRC ^ 0xffffffffL;}
4. Code files
READ_CONFIG.C file
#include <errno.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include < stddef.h> #include <string.h> #include <sys/types.h> #include <sys/ioctl.h> #include <sys/ stat.h> #include <unistd.h> #include "crc32.h" #define Mtd_path "/dev/mtdblock1" #define Mtd_offset0xf8000# Define mtd_env_size0x4000unsigned Char *envmatch (unsigned char * s1, unsigned char * s2); int main (int argc, char **argv) {i NT Fd;int I, len;unsigned char *buf, *p, *env;unsigned Long CRC, crc_calc;if (FD = open (Mtd_path, o_rdonly)) <0) {Fprin TF (stderr, "Can ' t Open%s:%s\n", Mtd_path, Strerror (errno)); return (-1);} if (Lseek (FD, Mtd_offset, Seek_set) < 0) {fprintf (stderr, "Can ' t locate OFFSET:%s \ n", Strerror (errno)); close (FD); Retu RN (-1);} if (buf = malloc (mtd_env_size)) = = NULL) {fprintf (stderr, "Can ' t alloc mem. %s\n ", Strerror (errno)); close (FD); return (-1);} if (len = Read (FD, buf, mtd_env_size))! = mtd_env_size) {fprintf (stderr, "read MTD failed! %s\n ", Strerror (errno)); close (FD); free (buf); return (-1);} memcpy (&CRC, buf, 4); if (CRC32 (0, buf+sizeof (long), mtd_env_size-sizeof (long))! = CRC) {fprintf (stderr, "Data CRC err Or!\n "); free (buf); close (FD); return (-1);} for (env = buf+sizeof (long); *env; env=p+1) {for (P = env; *p; p++) {if (P >= buf + mtd_env_size) {fprintf (stderr, "# # Error: "Environment not terminated\n"); return;}} if (argc = = 2) {if (Envmatch (argv[1], env) >0) {for (p=env; *p!= ' = '; p++);p rintf ("%s\n", ++p); break;} else continue;} El SE {printf ("%s\n", env);}} Free (BUF); close (FD); return 0;} /* * S1 is either a simple ' name ', or a ' name=value ' pair. * S2 is a ' name=value ' pair. * If the names match, return the value of S2, else NULL. */unsigned Char *envmatch (unsigned char * s1, unsigned char * s2) {while (*s1 = = *s2++) if (*s1++ = = ' = ') return (S2); if (*s 1 = = ' && * (s2-1) = = ' = ') return (S2); return (NULL);}
Makefile file, this because the basic is makefile blind, we make use of Ah, modify their respective cross_compile on it.
Cross_compile = powerpc-e300c3-linux-gnu-read_config:read_config.c crc32.o crc32.h$ (CROSS_COMPILE) gcc $^-o [email protected]crc32.o:crc32.c$ (cross_compile) gcc $^-c-o [email protected]clean:rm-f read_config CRC32.O