不同型号板子根目录下的文件数据读取【全·带注释】--详细注释文档在资源中

/*
 *说明:把分区0-6写到block0.txt-block6.txt中
*/

#include <stdio.h>
#include <sys/ioctl.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#include <sys/mount.h>
#include <sys/types.h>
#include <dirent.h>
#include <time.h>
#define SIZE_HEADER 128*1024  //systemheader
//区分海思或者联咏的板子
bool isHiChip=1;
int g_blocksize=0;
typedef struct BLOCK
{
    char dev[20];//路径
    long long size;//大小
    long int erasesize;
    char name[20];//名字
}BLOCK;

//记录写入文件偏移量
 //long long size=0;
//记录是NAND or Nor flash
 bool isNand=false;
 bool isN5064=false;
 
 //记录文本文件.txt的文件流指针
FILE *fb_txt=NULL;
void WriteFlash(long long FlashSize,int num);

/*
 *功能:把SourcePath路径下的文件拷贝到ReadBlock.txt中,
 *大小为ReadSize :‘M’为单位
 //(5064的正好读取的是字符5)所以,N5064型号的大小统计为 :ReadSize*1024*1024
 *SourcePath:分区0-6
 *ReadSize:分区的大小 单位(N5064:M),其他的是Byte
*/
void Copy_BlockFile(char *SourcePath,long ReadSize)
{
    long long size=0;
    long readlen=0;
    long writelen=0;
    long long writesize=0;

    char Buffer[1024*1024]={};
        //规定数组大小为1M,
        //1M=1024k=1048576字节
        //换算成中文汉字那么就是1M=524288个汉字(汉字占两个字节)

    long long pos1=0,pos2=0;
        //记录文件偏移的位置

    long long Realsize=ReadSize;
    if(isN5064)
       Realsize=1024LL*1024*ReadSize;//1024*1024 = 1M,这里要转换成以M为单位

//打开要读取的块设备路径下得文件
     FILE *fb_block=fopen(SourcePath,"rb");
    if(fb_block == NULL)
    {
        perror("fopen block:");
        return;
    }

//读文件
 while(1)
 {
     bzero(Buffer,sizeof(Buffer));
     //获取源文件的偏移量
     pos1=ftell(fb_block);

     //读的大小比Buffer数组小,可能是读完了或者发生错误
    if((readlen=fread(Buffer,1,sizeof(Buffer),fb_block))<sizeof(Buffer))
    {
        pos2=ftell(fb_block);
         //此时,pos1结束的光标是pos2的起始光标所在

        if(feof(fb_block))//读到文件的末尾
        {               
            writelen=fwrite(Buffer,1,pos2-pos1,fb_txt);
                //因为之前都是读取固定大小,所以这里需要
                //把剩余一点的部分文件内容也写到文件
			fflush(fb_txt);
                //写完刷新一下文本

            writesize+=writelen;
            size+=(pos2-pos1);
                /*writesize :向文本中写了多少剩余文件
                  size :若是每次读取的文件都恰好都小于数组
                   那么我们就每次都统计一下,看看读了多大空间的数据 */
            break;

        }
        else if (ferror(fb_block))
        {
            perror("fread");
            break;
        }


    }

    size+=readlen;
        //读完了写文件(读了多少字节的数据--这里是正好读完Buffer大小的数据,上面是读取的小)

    writelen=fwrite(Buffer,1,sizeof(Buffer),fb_txt);
	fflush(fb_txt);
        //每次写完文件,就擦除一下

    if(writelen<1048576)
    {
       fflush(fb_txt);
       writelen=fwrite(Buffer,1,sizeof(Buffer),fb_txt);
    }   /*
          1024*1024大小,防止读取出错(fb_txt文本中的内容正好有Buffer大小的话)->
          size是正好是数组从fb_block文本中读取数据的大小,writelen是将此前从fb_block文本读取到数组->
          中的数据写入到fb_txt文本的大小,(size+=readlen)==》既然是正好‘读’取了Buffer[]大小,那么这里->
          就和‘写’比较一下,多加一层判断,看看是不是也写了有1M大小的数据,如果没有1M,那就
          刷新一下文本,重新写一次。
                                                                              -- 2021/2/19修改
        */

    writesize+=writelen;
        //统计写了多少数据



// printf("\033[0;31m =====zyj Realsize=%lld,readlen=%ld,writelen=%ld,size=%lld,writesize=%lld\033[0;39m \n",Realsize,readlen,writelen,size,writesize);

}
  printf("\033[0;31m =====zyj Realsize=%lld,readsize=%lld,writesize=%lld\033[0;39m \n",Realsize,size,writesize);


//传进来的大小比实际读取的大小【大】的话,读取完文件后把那部分多余的空间填充0xff
if(Realsize>size)
{
    if(isN5064==true)
     WriteFlash(Realsize-size,0x00);
    else
     WriteFlash(Realsize-size,0xff);//其他型号剩余空间填入0xff
}



 //关闭文件
  fclose(fb_block);



}
/*
 *功能:往fb_txt所指向的文件写入num,大小为flashsize个字节
 *FlashSize:内存大小如:空余的分区
 *num:要写入的数入:0xff
 */
void WriteFlash(long long FlashSize,int num)
{
    //printf("\033[0;31m =====zyj FlashSize=%lld\033[0;39m \n",FlashSize);

    char Buffer[1024*1024]={};
        //读取完文件后把剩余的空间填充0xff

    int i=0,writesize=0;
    int a = 0;

    int times=FlashSize/sizeof(Buffer);
        //多余空间填充的次数
        //例如:假设型号数据大小是3M,那么便要计算需要添加几次sizeof(Buffer)/sizeof(num)大小的oxff

    for(i=0;i<times;i++)
    {
        memset(Buffer,num,sizeof(Buffer));
        a = fwrite(Buffer,sizeof(num),sizeof(Buffer)/sizeof(num),fb_txt);
		fflush(fb_txt);
        writesize += a; //sizeof(Buffer);

    }

    memset(Buffer,num,sizeof(Buffer));

    if(FlashSize>writesize)
    fwrite(Buffer,sizeof(num),FlashSize-writesize,fb_txt);//把最后一次文件写入0xff
	fflush(fb_txt);

}

/*说明:根据不同的chip来获取mtd_block信息(分区名字,大小)
 * 联咏读取/proc/mtd 海思读取/proc/cmdline
 * NOR flash 读/dev/mtdbloack NAND: /dev/mtd
 *参数:mtd_block: 保存板子的分区的信息(名字,大小)
*/
void Read_Mtdsize(BLOCK *mtd_block)
{
   char *ptr=NULL;//用于字符串分割的
   char ptr_size[20]={};//用于字符串分割的
   char ptr_erasize[20]={};//用于字符串分割的
   char *arr_ptr[20]={};//用于存放第一次分割的字符串
   char * token=NULL;
   char readbuf[200]={};
   // 联咏
   if(isHiChip==false)
   {

       FILE *fb_mtd=fopen("/proc/mtd","r");
       if(fb_mtd==NULL)
       {
            perror("fopen mtd:");
            return ;
       }
       //跳过第一行
       fgets(readbuf,sizeof(readbuf),fb_mtd);
     while(1)
     {
       if(fgets(readbuf,sizeof(readbuf),fb_mtd)==NULL)
       {
           break;
       }


       sscanf(readbuf,"%s %s %s %s",mtd_block[g_blocksize].dev,ptr_size,ptr_erasize,mtd_block[g_blocksize].name);
       mtd_block[g_blocksize].size = strtol(ptr_size,&ptr,16);
        mtd_block[g_blocksize].erasesize = strtol(ptr_erasize,&ptr,16);

       //记录读的行数
        g_blocksize++;

      }


        fclose(fb_mtd);


   }//海思平台读取/proc/cmdline
   else if(isHiChip==true)
   {
       FILE *fb_cmdline=fopen("/proc/cmdline","r");
       if(fb_cmdline==NULL)
       {
            perror("fopen mtd:");
            return ;
       }
            bzero(readbuf,sizeof(readbuf));
            //一次性把/proc/cmdline文件全部读到readbuf中
           fread(readbuf,1,sizeof(readbuf),fb_cmdline);

            ptr = strstr(readbuf,"mtdparts=");
            if(strstr(ptr,"hinand")!=NULL)
                isNand=true;
            else
                isNand=false;

            //将字符串拆分成6M(boot)格式
            if(ptr)
            {
                 token = strtok(ptr,":,");

            }


            while(token!=NULL)
            {
                token = strtok(NULL,":,");

                if(token!=NULL){
                    arr_ptr[g_blocksize]=token;
                    g_blocksize++;
                    if(strstr(token,"p2p"))
                        break;
                }

            }


     //拆分字符串arr_ptr中的字符串给mtd_block中的分区名字,大小
        int i=0;
        for(i=0;i<g_blocksize;i++)
        {
            token = strtok(arr_ptr[i],"()");
            if(strstr(token,"M")!=NULL)
            {
               mtd_block[i].size =1024*1024*strtol(token,&ptr,10);
              // printf("\033[0;31m =====zyj size=%ld\033[0;39m \n",mtd_block[i].size);

            }
            else if(strstr(token,"K")!=NULL)
            {
                mtd_block[i].size =1024*strtol(token,&ptr,10);
                //printf("\033[0;31m =====zyj size=%ld\033[0;39m \n",mtd_block[i].size);

            }


            token = strtok(NULL,"()");
            strcpy(mtd_block[i].name,token);


            if(isNand)
            sprintf(mtd_block[i].dev,"/dev/mtd%d",i);
            else if(!isNand)
            sprintf(mtd_block[i].dev,"/dev/mtdblock%d",i);
            //printf("\033[0;31m =====zyj %d:dev=%s,size=%x,erasesize=%x,name=%s\033[0;39m \n",i,mtd_block[i].dev,mtd_block[i].size,mtd_block[i].erasesize,mtd_block[i].name);


        }
        //printf("\033[0;31m =====zyj isNand=%d\033[0;39m \n",isNand);



        fclose(fb_cmdline);

   }


}
/*
 * 功能:获取板子的芯片平台
 */
void Get_CPlatform()
{
    char *ptr=NULL;
    char readbuf[200]={};

    FILE *fb_cmdline=fopen("/proc/cmdline","r");
    if(fb_cmdline==NULL)
    {
         perror("fopen mtd:");
         return ;
    }
         bzero(readbuf,sizeof(readbuf));
         //一次性把/proc/cmdline文件全部读到readbuf中
        if(fread(readbuf,1,sizeof(readbuf),fb_cmdline)==0)
            return;

         if(strstr(readbuf,"hinand")||strstr(readbuf,"hi_sfc"))
             isHiChip=true; //海思
         else
             isHiChip=false;//联咏
         printf("\033[0;31m =====zyj isHiChip=%d\033[0;39m \n",isHiChip);

        fclose(fb_cmdline);
    return ;
}

/*说明:读取/proc/cmdline拆分获得分区的名字和大小
 *  * 特殊的型号A01_EMMC另外处理/proc/cmdline
 * mtd_block: 保存板子的分区的信息(名字,大小)
 */
void Read_Mmcblksize(BLOCK *mtd_block)
{
    char readbuf[500]={};
    char *ptr=NULL;//用于字符串分割的(辅助使用)
    char *arr_ptr[25]={};//用于存放第一次分割的字符串
    char * token=NULL;
    FILE *fb_cmdline=fopen("/proc/cmdline","r");
    if(fb_cmdline==NULL)
    {
         perror("fopen mtd:");
         return ;
    }
     bzero(readbuf,sizeof(readbuf));
     fread(readbuf,1,sizeof(readbuf),fb_cmdline);
        //一次性把/proc/cmdline文件全部读到readbuf中

     ptr = strstr(readbuf,"mmcblk0:");

     token = strtok(ptr,":,");
      //返回分解后的字符串的起始位置指针
     while(token!=NULL)
     {
         token = strtok(NULL,":,");
         if(strstr(token,"vmalloc"))
             break;
         arr_ptr[g_blocksize]=token;
            //存储拆分后的字符串
         g_blocksize++;
            //统计分割的区间个数

     }

     //拆分字符串arr_ptr中的字符串给mtd_block中的分区名字,大小
        int i=0;
        for(i=0;i<g_blocksize;i++)
        {
            token = strtok(arr_ptr[i],"()");
           if(strstr(token,"M")!=NULL)
            {
                 mtd_block[i].size =strtol(token,&ptr,10);

                 //printf("\033[0;31m =====zyj  [%d]:size=%llu\033[0;39m \n",i,mtd_block[i].size);
            }
           else if(strstr(token,"K")!=NULL)
            {
                 mtd_block[i].size =strtol(token,&ptr,10)/1024;
                                            //转换成M为单位的大小(如:1024K/1024 == 1)
                 //printf("\033[0;31m =====zyj  [%d]:size=%llu\033[0;39m \n",i,mtd_block[i].size);
            }

            sprintf(mtd_block[i].dev,"/dev/mmcblk0p%d",i+1);

         }
}
/*
 * 功能:获取板子的boardif
 */
void Get_boardid(char boardid[])
{
    char buf[128]={};
    char *ptr=NULL;

    FILE *fb=popen("readkeyboardid","r");
    if(fb == NULL)
    {
        perror("popen");
        return;
    }
    fread(buf,1,sizeof(buf),fb);//将fp的数据流读到buff中
    ptr=strstr(buf,"boardid =");//接收字符串"boardid =",在数组中首次出现的地址

    sscanf(ptr,"boardid = %s",boardid);//把从ptr地址开始的字符串“boardid =”后面的字符按照%s的格式写入到boardid数组中
                                       //sscanf函数 :https://www.cnblogs.com/wubiyu/archive/2008/11/20/1337835.html
    printf("\033[0;31m =====zyj BoardId=%s\033[0;39m \n",boardid);

    pclose(fb);
    return ;
}


int main(int argc,char**argv)
{

    clock_t a,b;
    a=time(NULL);
    int i=0;
    char mtdpath[50]={};//分区路径
    char boardid[20]={};//保存boardid
    //结构体数组用来记录分区的名字和长度
     BLOCK mtd_block[23]={};

    fb_txt= fopen("./ReadBlock","wb+");
        //这个文件是用来存放我们的拷贝数据
    if(fb_txt == NULL)
    {
          perror("fopen txt:");
          return -1;
    }


    Get_boardid(boardid);
    if(strcmp(boardid,"N5064PN-EMMC")==0)//是N5064的板子
    {
        isN5064=true;
        //A01_EMMC的板子
        long long blocksize=0;

        Read_Mmcblksize(mtd_block);
            //读取分区路径下得名字和大小

        for(i=0;i<g_blocksize;i++)
        {
            Copy_BlockFile(mtd_block[i].dev,mtd_block[i].size);

            blocksize+=1024*1024*mtd_block[i].size;
                   //mtd_block[i].size :为数字;在乘以1M(两个1024)后,转为xM大小
        }
         WriteFlash(8LL*1024*1024*1024-blocksize,0x00);

    }
    else //其他板子
    {
        Get_CPlatform();

         if(isHiChip==false)
         {
             if(strcmp(boardid,"D7108NR")==0||strcmp(boardid,"D8116NR")==0){
               Copy_BlockFile("/tmp/usb/header.bin",SIZE_HEADER);
                    //分区路径以及大小
             }

             Read_Mtdsize(mtd_block);

             for(i=0;i<g_blocksize-1;i++)
             {
                 //NT板子都是nand flash
                  sprintf(mtdpath,"/dev/mtd%d",i);
                  Copy_BlockFile(mtdpath,mtd_block[i].size);

             }
         }
         else if(isHiChip==true)
         {

             memset(mtdpath,0,sizeof(mtdpath));
             Read_Mtdsize(mtd_block);
             for(i=0;i<g_blocksize;i++)
             {
                 Copy_BlockFile(mtd_block[i].dev,mtd_block[i].size);
             }

         }

    }


    fclose(fb_txt);
     b=time(NULL);

   printf("\033[0;31m =====*zyj end time=%f \033[0;39m \n",(float)(b-a));
    //程序运行结束,用了多久

    return 0;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

扳手的海角

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值