[ Linux Busybox ] flash_eraseall 命令解析

文章目录

    • 相关结构体
    • flash_eraseall 函数实现
    • flash_eraseall 实现流程图


文件路径:busybox-1.20.2/miscutils/flash_eraseall.c

相关结构体

MTD 相关信息结构体

struct mtd_info_user {
    __u8 type;              // MTD 设备类型
    __u32 flags;            // MTD设备属性标志
    __u32 size;             // mtd设备的大小
    __u32 erasesize;        // MTD设备的擦除单元大小,对于 NandFlash来说就是 Block的大小
    __u32 writesize;        // MTD设备的读写单元大小,对于 NandFlash来说就是page 的大小
    __u32 oobsize;          // oob区域大小
    __u64 padding;          // 有效的oob区域大小
};

flash_eraseall 函数实现

假如内核位于第二个分区,即mtd2,在擦除该分区时使用的命令是:./flash_eraseall /dev/mtd2

int flash_eraseall_main(int argc UNUSED_PARAM, char **argv)
{
    struct jffs2_unknown_node cleanmarker;
    mtd_info_t meminfo;
    int fd, clmpos, clmlen;
    erase_info_t erase;
    struct stat st;
    unsigned int flags;
    char *mtd_name;

    opt_complementary = "=1";
    flags = BBTEST | getopt32(argv, "jq");    // 获取命令行中参数

    mtd_name = argv[optind];
    fd = xopen(mtd_name, O_RDWR);        // 打开设备/dev/mtd2
    fstat(fd, &st);        
    if (!S_ISCHR(st.st_mode))            // 判断设备/dev/mtd2 是否为字符设备
        bb_error_msg_and_die("%s: not a char device", mtd_name);

    xioctl(fd, MEMGETINFO, &meminfo);        // 获取内存信息,参看结构体1
    erase.length = meminfo.erasesize;
    if (meminfo.type == MTD_NANDFLASH)
        flags |= IS_NAND;

    clmpos = 0;
    clmlen = 8;
    if (flags & OPTION_J) {                // jffs2格式化分区
        uint32_t *crc32_table;

        crc32_table = crc32_filltable(NULL, 0);

        cleanmarker.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
        cleanmarker.nodetype = cpu_to_je16(JFFS2_NODETYPE_CLEANMARKER);
        if (!(flags & IS_NAND))
            cleanmarker.totlen = cpu_to_je32(sizeof(struct jffs2_unknown_node));
        else {
            struct nand_oobinfo oobinfo;

            xioctl(fd, MEMGETOOBSEL, &oobinfo);

            /* Check for autoplacement */
            if (oobinfo.useecc == MTD_NANDECC_AUTOPLACE) {
                /* Get the position of the free bytes */
                clmpos = oobinfo.oobfree[0][0];
                clmlen = oobinfo.oobfree[0][1];
                if (clmlen > 8)
                    clmlen = 8;
                if (clmlen == 0)
                    bb_error_msg_and_die("autoplacement selected and no empty space in oob");
            } else {
                /* Legacy mode */
                switch (meminfo.oobsize) {
                case 8:
                    clmpos = 6;
                    clmlen = 2;
                    break;
                case 16:
                    clmpos = 8;
                    /*clmlen = 8;*/
                    break;
                case 64:
                    clmpos = 16;
                    /*clmlen = 8;*/
                    break;
                }
            }
            cleanmarker.totlen = cpu_to_je32(8);
        }

        cleanmarker.hdr_crc = cpu_to_je32(
            crc32_block_endian0(0, &cleanmarker, sizeof(struct jffs2_unknown_node) - 4, crc32_table)
        );
    }

    /* Don't want to destroy progress indicator by bb_error_msg's */
    applet_name = xasprintf("\n%s: %s", applet_name, mtd_name);

    for (erase.start = 0; erase.start < meminfo.size;    // 循环擦除flash芯片,按块大小擦除 meminfo.erasesize
         erase.start += meminfo.erasesize) {
        if (flags & BBTEST) {
            int ret;
            loff_t offset = erase.start;

            ret = ioctl(fd, MEMGETBADBLOCK, &offset);        //通过offset,判定该偏移处是否是坏块
            if (ret > 0) {
                if (!(flags & OPTION_Q))                    //  判断是否为静默模式(不打印信息)
                    bb_info_msg("\nSkipping bad block at 0x%08x", erase.start);
                continue;
            }
            if (ret < 0) {            // block块表是不可用的某些flash类型,如NOR
                /* Black block table is not available on certain flash
                 * types e.g. NOR
                 */
                if (errno == EOPNOTSUPP) {
                    flags &= ~BBTEST;
                    if (flags & IS_NAND)
                        bb_error_msg_and_die("bad block check not available");
                } else {
                    bb_perror_msg_and_die("MEMGETBADBLOCK error");
                }
            }
        }
        //更新擦除进度条
        if (!(flags & OPTION_Q))
            show_progress(&meminfo, &erase);

        // 块擦除操作
        xioctl(fd, MEMERASE, &erase);

        /* format for JFFS2 ? */
        if (!(flags & OPTION_J))
            continue;

        /* write cleanmarker */
        if (flags & IS_NAND) {
            struct mtd_oob_buf oob;

            oob.ptr = (unsigned char *) &cleanmarker;
            oob.start = erase.start + clmpos;
            oob.length = clmlen;
            xioctl(fd, MEMWRITEOOB, &oob);
        } else {
            xlseek(fd, erase.start, SEEK_SET);
            /* if (lseek(fd, erase.start, SEEK_SET) < 0) {
                bb_perror_msg("MTD %s failure", "seek");
                continue;
            } */
            xwrite(fd, &cleanmarker, sizeof(cleanmarker));
            /* if (write(fd, &cleanmarker, sizeof(cleanmarker)) != sizeof(cleanmarker)) {
                bb_perror_msg("MTD %s failure", "write");
                continue;
            } */
        }
        if (!(flags & OPTION_Q))
            printf(" Cleanmarker written at %x.", erase.start);
    }
    if (!(flags & OPTION_Q)) {
        show_progress(&meminfo, &erase);
        bb_putchar('\n');
    }

    if (ENABLE_FEATURE_CLEAN_UP)
        close(fd);
    return EXIT_SUCCESS;
}

注:
cleanmarker是用于标记一个块是否完整地被擦除的。 在Flash存储器中,只有在块完整地擦除后才能进行写入操作。这是因为在某些特殊情况下,比如系统在擦除周期末尾重启,可能导致Flash中的位不稳定,即读出的值可能在不同时间点不一致。为了解决这个问题,引入了cleanmarker来标记块是否真正完整地擦除。

在制作jffs2文件系统时,由于文件系统会对块进行管理,因此不再需要使用cleanmarker标记。 在制作文件系统时,可以使用-n或–no-cleanmarker选项来表示不使用cleanmarker。这意味着在第一次挂载文件系统时,cleanmarker并不重要。而在使用mtd工具flash_eraseall对Flash进行格式化时,应该使用 -j 参数来带上cleanmarker标记。这样,在擦除完Flash后,会在oob(out-of-band)区域设置相应的cleanmark位,表示该块已经完整擦除。这样,在以后对该块进行操作时,jffs2文件系统可以发现该块已经被擦除,从而避免浪费时间重新擦除已经是0xff的块。


flash_eraseall 实现流程图

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/120528.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

一篇文章带你搞懂DNS全流程

1.DNS与CDN DNS是域名系统的缩写&#xff0c;它是一种将域名和IP地址相互映射的分布式数据库&#xff0c;能够使人更方便地访问互联网。 DNS的主要功能是将域名解析为IP地址。当你在浏览器中输入一个网址时&#xff0c;浏览器会向DNS服务器发送一个请求&#xff0c;以获取该网…

如何使用 JMeter 进行 HTTPS 请求测试?

本文将介绍如何使用 JMeter 测试 HTTPS 请求&#xff0c;并提供相关的技巧和注意事项。 在进行性能测试时&#xff0c;很多网站都采用了 HTTPS 协议。当我们测试 HTTPS 请求&#xff0c;如果服务端开启了双向认证&#xff0c;则需要客户端发送请求时带上证书。本文介绍如何在 …

换服还是掀桌?哪条才是程序员的出路?

站在时代的风口浪尖&#xff0c;猪都能起飞。 大数据互联网正是时代的宠儿&#xff0c;IT行业的发展也正如火如荼。 人人都眼红程序员的高薪资&#xff0c;认为他们吃着时代的红利。 但是三百六十行&#xff0c;行行出社畜。”996“也好&#xff0c;甚至"007"也罢…

软件测试面试题【2023最新合集】

收集了各大公司的面试经验&#xff0c;现整理出来&#xff0c;希望能给正在找工作的志同道合的小伙伴一些指引&#xff0c;本文会持续更新的哦。 1、 CPU 和 GPU的区别 一个是通用计算&#xff0c;一个是专用计算。 CPU主要负责操作系统和应用程序&#xff0c;GPU主要负责跟…

TensorFlow学习笔记--(1)张量的随机生成

张量的生成 如何判断一个张量的维数&#xff1a;看张量的中括号有几层 0 1 2 &#xff1a;零维数列 [2 4 6] : 一维向量 [ [1 2 3] [4 5 6] ] : 二维数组 两行三列 第一行数据为 1 2 3 第二行数据为 4 5 6 以此类推 n维张量有n层中括号 tf.zeros(%指定一个张量的维数%) 生成一…

汽车标定技术(二)--基于XCP的标定测量实战

目录 1.工程创建 1.1 新建工程 1.2 设备配置 1.3 标定观测 1.4 刷写 2.原始hex文件与标定文件的合并 2.1 修改memory segment file 2.2 标定量地址偏移 ​编辑 2.3 标定后与原始hex文件合并 2.4 标定后直接merge 2.5 不用对ram地址进行偏移实现hex文件合并 本文使用…

【机器学习】梯度下降预测波士顿房价

文章目录 前言一、数据集介绍二、预测房价代码1.引入库2.数据3.梯度下降 总结 前言 梯度下降算法学习。 一、数据集介绍 波士顿房价数据集&#xff1a;波士顿房价数据集&#xff0c;用于线性回归预测 二、预测房价代码 1.引入库 from sklearn.linear_model import Linear…

【Docker】设置容器系统字符集zh_CN.UTF-8退出失效:关于Docker容器配置环境变量,再次进入失效问题

设置容器系统字符集zh_CN.UTF-8退出失效&#xff1a;关于Docker容器配置环境变量&#xff0c;再次进入失效问题 修改正在运行的Docker容器内的字符集: 先进入Docker容器&#xff1a;docker exec -it 容器ID /bin/bash查看是否支持中文字符集&#xff1a;locale -a | grep zh&a…

案例 | 3D可视化工具HOOPS助力SolidWorks edrawings成功引入AR/VR技术

HOOPS中文网慧都科技是HOOPS全套产品中国地区指定授权经销商&#xff0c;提供3D软件开发工具HOOPS售卖、试用、中文试用指导服务、中文技术支持。http://techsoft3d.evget.com/达索系统SolidWorks面临的挑战 达索系统SolidWorks公司开发和销售三维CAD设计软件、分析软件和产品…

五、计算机网络

&#xff08;一&#xff09;OSI/RM 七层模型 七层模型是计算机网络的基石&#xff0c;整个计算机网络是构建与七层模型之上的。 在数据链路层&#xff0c;数据开始以帧为单位&#xff0c;网卡的 MAC 地址就是数据帧的地址&#xff0c;数据的传输开始有地址了。 局域网是工作…

国自然中标越来越难,怎样才能赢在起跑线上?

众所周知&#xff0c;国自然在学术界的地位和影响力不容小觑。“国自然在手&#xff0c;天下我有”&#xff0c;对于科研人来说&#xff0c;成功申报国自然&#xff0c;有助于职称评审、职业升迁&#xff0c;同时&#xff0c;获得不菲的科研经费。据了解&#xff0c;有些高校还…

https网站加载http资源问题

https网站加载http资源问题 前言&#xff1a;最近项目对接了一个第三方的平台、我们需要展示第三方平台返回来的图片资源、由于我们的服务器设置为了https、但是第三方平台返回的图片链接是 http 资源。所以就出现了图片无法加载出来的问题&#xff0c;在此记录一下问题的解决…

ps人像怎么做渐隐的效果?

photoshop怎么制作人像渐隐的图片效果&#xff1f;渐隐效果需要使用渐变来实现&#xff0c;下面我们就来看看详细的教程。 首先&#xff0c;我们打开Photoshop&#xff0c;点击屏幕框选的【打开】&#xff0c;打开一张背景图片。 下面&#xff0c;我们点击左上角【文件】——【…

如何在Jetpack Compose中显示PDF?

当读取和显示 PDF 的组件缺失时该怎么办? 声明式编程可以拯救你. Jetpack Compose已经存在好几年了, 但_在某些方面它的使用仍然面临挑战_. 例如, 缺少用于查看PDF的官方组件, 而为数不多的第三方库通常也是有代价的. 在我们的应用中, 我们会遇到在许多场景中显示 PDF 的需求…

1.1 HTML4

一. 前言 1. 两位先驱 艾伦麦席森图灵 二战时期&#xff0c;破译了德军的战争编码一英格玛。让二战提前2年结束&#xff0c;拯救了上千万人的生命。设立图灵奖&#xff0c;被后人誉为:人工智能之父。 约翰冯诺依曼 制订了现代计算机标准一一冯诺依曼体系结构。提出:计算机要…

目标检测中的评价指标

目标检测中的评价指标 将检测目标分为正样本和负样本。 真阳性&#xff08;true positives , TP&#xff09; : 正样本被正确识别为正样本。 假阳性&#xff08;false positives, FP&#xff09;: 负样本被错误识别为正样本。 假阴性&#xff08;false negatives, FN&#…

微服务项目,请求从发出到后端处理器的历程

点击登录按钮,发出 http://localhost:8803/service_6001/admin/login/in请求,这是一个由nginx配置的前端项目 查看配置文件,该条请求会被映射形成对http://localhost:51603/admin/login/in的post请求 upstream heima-admin-gateway {server localhost:51603; } server {liste…

Spring Cloud之多级缓存

目录 传统缓存 多级缓存 JVM进程缓存 Caffeine 缓存驱逐策略 实现进程缓存 常用Lua语法 数据类型 变量声明 循环使用 定义函数 条件控制 安装OpenResty 实现Nginx业务逻辑编写 请求参数解析 实现lua访问tomcat JSON的序列化和反序列化 Tomcat的集群负载均衡 …

20231106-前端学习加载和视频球特效

加载效果 代码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>加载效果</title><!-- 最新…