[ 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/mtd2fstat(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); // 获取内存信息,参看结构体1erase.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.erasesizeerase.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 实现流程图

相关文章:
[ 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设…...
RabbitMQ 消息中间件 消息队列
RabbitMQ1、RabbitMQ简介2、RabbitMQ 特点3、什么是消息队列4、RabbiMQ模式5、集群中的基本概念 单实例安装RabbitMQ安装依赖安装erlang安装rabbitmq开启rabbitmq的web访问界面添加用户修改配置文件重启服务浏览器访问Rabbit-test rabbitMQ集群准备工作(三台&#x…...
ChatGPT王炸升级GPT-4 Turbo:更强大还更便宜
11月7日,OpenAI首届开发者大会如期召开,在大会上OpenAI正式推出了GPT-4 Turbo。 据OpenAI介绍,相比于GPT-4,GPT-4 Turbo主要有6方面的提升: 第一,上下文对话长度,GPT4最大只能支持8k的上下文长…...
3.JMeter高级使用-让你与众不同
目录 概述插件下载与安装插件下载配置插件 服务器硬件资源监控(精简版)配置服务端代理JMeter配置监控CPU监控网络 JMeter下载结束 概述 今日目标: 插件下载与安装Basic Graphs 主要点 Average Response Time 平均响应时间Active Threads 活动线程数Successful/Fai…...
考研408-计算机网络 第一章-计算机网络体系结构学习笔记及习题
第一章 计算机网络体系结构 一 计算机网络概述 1.1 概念及功能 1.1.1 计算机网络的概念 计算机网络就是互连的、自治的计算机系统的集合 互连:通过通信链路互联互通 自治:各个节点之间无主从关系,高度自治的 1.1.2 计算机网络的功能 功…...
【快速使用ShardingJDBC的哈希分片策略进行分库分表】
文章目录 🔊博主介绍🥤本文内容🍊1.引入maven依赖🍊2.启动类上添加注解MapperScan🍊3.添加application.properties配置🍊4.普通的自定义实体类🍊5.写个测试类验证一下🍊6.控制台打印…...
102. 二叉树的层序遍历
原题链接:102. 二叉树的层序遍历 以下代码为模板,需要层序遍历时都可以使用该模板进行代码更改 全代码: class Solution { public:vector<vector<int>> levelOrder(TreeNode* root) {//创建一个TreeNode* 队列用于存储树中的每…...
macOS磁盘分区调整软件--Paragon Camptune X 中文
Paragon Camptune X是一款专为Mac用户设计的强大分区大小调整工具。通过它,用户可以简便地调整Mac硬盘上的分区大小,实现存储空间的高效管理。无论是需要在Mac和Windows系统之间切换的双系统用户,还是有其他特定存储需求的用户,Ca…...
kaggle中报错NameError: name ‘q_1‘ is not defined
在开始练习之前,先点击“全部运行”按钮。...
SQL注入漏洞 其他注入
文章目录 宽字节注入案例 HTTP头部注入Cookie注入base64User-Agent注入Referer 注入 SQL注入读写文件条件1.是否拥有读写权限2.文件路径3.secure_file_priv 读取文件写入文件 SQLMap安装sqlmapkail 源安装仓库克隆 参数简介快速入门;SQLmap(常规…...
Java自学第2课:Java语言基础知识要点
1 Java主类结构 任务:创建新项目名为item,包名为number,类名为first。 1.1 包声明 不指定包时,默认就是工程名,指定后,类文件可以分类了,是这意思吧。包就大概等于一个文件夹。而且在类文件中…...
flink状态和检查点
检查点和状态后端的区别 检查点 就是某个时间点下的所有算子的状态快照。这个时间点就是等所有任务将“同一个数据”处理完毕的时候。 状态后端:是一个管理状态的组件,还负责将本地状态(检查点)持久化到远程文件存储系统中。 分…...
数据仓库工具箱-零售业务
文章目录 一、维度模型设计的4步过程1.1 第一步:选择业务过程1.2 第二步:声明粒度1.3 第三步:确定维度1.4 第四步:确定事实 二、零售业务案例研究2.1 第一步:选择业务过程2.2 第二步:声明粒度2.3 第三步&am…...
网络工程实验记录
网络工程 show ip route show running-config 第一周 相同设备使用交叉线,不同设备之间使用直通线 R1能ping通10.1.1.1 R2能ping通所有的 R3能ping通172.16.1.1 即路由器只能到达自身线连接出去的,另一端就连接不了了。 此时给R1分配静态路由 R…...
Danswer 接入 Llama 2 模型 | 免费在 Google Colab 上托管 Llama 2 API
一、前言 前面在介绍本地部署免费开源的知识库方案时,已经简单介绍过 Danswer《Danswer 快速指南:不到15分钟打造您的企业级开源知识问答系统》,它支持即插即用不同的 LLM 模型,可以很方便的将本地知识文档通过不同的连接器接入到…...
react:路由
官方文档:https://reactrouter.com/en/main/start/overview#pending-navigation-ui 一:简单版本 先 npm i react-router-dom main.ts中内容替换为 import ReactDOM from react-dom/client import App from ./App.tsx import ./index.css import {creat…...
【AI工具】手把手带你使用Gradio分享你的模型
手把手带你使用Gradio分享你的模型 1. 快速入门2. 基本参数|支持的接口2.1 Interface类以及基础模块2.2 组件属性2.3 多输入输出组件2,4 图像组件2.5 Chatbots2.6 动态界面接口2.7 Blocks:更具灵活性和调控性2.7.1 Blocks入门2.7.2 更复杂的Blocks3. 分享自定义采样训练参考资…...
海洋专用cmocean颜色包_共22种--全平台可用
海洋专用cmocean颜色包_共22种–全平台可用 往期推荐: Python语言_matplotlib包_共80种–全平台可用 Python语言_single_color_共140种–全平台可用 R语言_RColorBrewer包–全平台可用 R语言gplots包的颜色索引表–全平台可用 R语言中的自带的调色板–五种–全平台…...
uni-app多端开发
uni-app 多端开发 一、命令创建uni-app 项目二、在微信小程序后台找到 appId 填写 appId三、运行项目四、使用 uni-ui4-1、下载4-2、自动导入4-3、ts项目下载类型校验 (uni-ui 组件库)4-3-1、下载4-3-2、配置 五、持久化 pinia六、数据请求封装七、获取组…...
Linux中固定ip端口和修改ip地址
一,更改虚拟网络编辑器 1,首先启动VMware,选择自己要更改ip或固定ip的虚拟机,并找到虚拟网络配编辑器,点击进入 2,进入之后需要点击右下角获取管理员权限后才能修改,有管理员权限之后图片如下 …...
变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析
一、变量声明设计:let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性,这种设计体现了语言的核心哲学。以下是深度解析: 1.1 设计理念剖析 安全优先原则:默认不可变强制开发者明确声明意图 let x 5; …...
TDengine 快速体验(Docker 镜像方式)
简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能,本节首先介绍如何通过 Docker 快速体验 TDengine,然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker,请使用 安装包的方式快…...
大话软工笔记—需求分析概述
需求分析,就是要对需求调研收集到的资料信息逐个地进行拆分、研究,从大量的不确定“需求”中确定出哪些需求最终要转换为确定的“功能需求”。 需求分析的作用非常重要,后续设计的依据主要来自于需求分析的成果,包括: 项目的目的…...
从零实现富文本编辑器#5-编辑器选区模型的状态结构表达
先前我们总结了浏览器选区模型的交互策略,并且实现了基本的选区操作,还调研了自绘选区的实现。那么相对的,我们还需要设计编辑器的选区表达,也可以称为模型选区。编辑器中应用变更时的操作范围,就是以模型选区为基准来…...
MFC内存泄露
1、泄露代码示例 void X::SetApplicationBtn() {CMFCRibbonApplicationButton* pBtn GetApplicationButton();// 获取 Ribbon Bar 指针// 创建自定义按钮CCustomRibbonAppButton* pCustomButton new CCustomRibbonAppButton();pCustomButton->SetImage(IDB_BITMAP_Jdp26)…...
无法与IP建立连接,未能下载VSCode服务器
如题,在远程连接服务器的时候突然遇到了这个提示。 查阅了一圈,发现是VSCode版本自动更新惹的祸!!! 在VSCode的帮助->关于这里发现前几天VSCode自动更新了,我的版本号变成了1.100.3 才导致了远程连接出…...
1688商品列表API与其他数据源的对接思路
将1688商品列表API与其他数据源对接时,需结合业务场景设计数据流转链路,重点关注数据格式兼容性、接口调用频率控制及数据一致性维护。以下是具体对接思路及关键技术点: 一、核心对接场景与目标 商品数据同步 场景:将1688商品信息…...
Java-41 深入浅出 Spring - 声明式事务的支持 事务配置 XML模式 XML+注解模式
点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) 目前2025年06月05日更新到: AI炼丹日志-28 - Aud…...
Go 并发编程基础:通道(Channel)的使用
在 Go 中,Channel 是 Goroutine 之间通信的核心机制。它提供了一个线程安全的通信方式,用于在多个 Goroutine 之间传递数据,从而实现高效的并发编程。 本章将介绍 Channel 的基本概念、用法、缓冲、关闭机制以及 select 的使用。 一、Channel…...
uniapp手机号一键登录保姆级教程(包含前端和后端)
目录 前置条件创建uniapp项目并关联uniClound云空间开启一键登录模块并开通一键登录服务编写云函数并上传部署获取手机号流程(第一种) 前端直接调用云函数获取手机号(第三种)后台调用云函数获取手机号 错误码常见问题 前置条件 手机安装有sim卡手机开启…...
