Mpc8313erdb Code Analysis of Uboot environment variables read from NAND flash in Linux
[Email protected]
One. Story cause
Due to the increase of the file system, it has greatly exceeded the 8MB nor FLASH. Instead, the kernel, file system, and device tree files have to be saved to NAND flash.
However, 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 a unified ramdisk. And after implementing Linux boot. Set to the function of the parameters can not be more convenient is to pass these parameters from the Uboot passed, this got everyone's certification, we can directly join the startup parameters, and then read out in the kernel, such a method of comparison. The only downside is the need to change the kernel. ,
In addition, the corresponding parameters are written to NAND flash in the form of uboot environment variables. And then read it in Linux. This method is relatively good, do not change the kernel, do not change the LTIB inside the standard package can be completed.
。。
In fact, Uboot comes with code that reads and writes environment variables under Linux. Under Uboot/tools/env This folder, of course. You can also use the: "Make env" to compile directly. In the same folder will generate fw_printenv this executable file, then, you need to change the configuration Fw_env.config, and then put it in your file system: "/etc/fw_env.config". Build two more soft links to be able,,,
The process is more complicated, and I'm using the u-boot-1.3.0 code. The result is that when you make env, there is a mistake, and you can try to compile and look at it. Assuming that you can pass it once, you can not debug it ~
In fact, it is very easy to read the UBOOT environment variables below Linux.
is the main file read, and string analysis, mainly to figure out where your NAND flash environment variables are stored.
Here is a sample I wrote based on Fw_printenv, which can compile and read the environment variables in NAND.
。
Two.
Detailed implementation
1. Determine uboot environment parameters save location in Flash
Because I use MPC8313ERDB this board. So looking at the Uboot code "include/configs/mpc8313erdb.h" This definition file has the following definitions:
#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
Since I am 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
Same reason. You can also check the corresponding definition in the Include/configs folder based on what board you are using.
2. Read the Uboot MTD file
By determining the offset of the environment variable in Flash, the Uboot MTD device file can be opened directly. Then use the Lseek to locate, and then use the Read function to read the UBOOT environment variables.
So here it is. Uboot exactly which MTD device is different from your device tree file. Of course, you can also directly under the Linux execution command "CAT/PROC/MTD" inside to check.
3. CRC check
How is it correct to be sure that the data is read? In fact, where the UBOOT environment variable starts. A 4-byte, 32-bit CRC checksum is saved. We can verify that,.
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 is because the basic is makefile blind, we make use of it ha. You can change the cross_compile of your own.
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
Mpc8313erdb Code Analysis of Uboot environment variables read from NAND flash in Linux