mirror of
https://github.com/apache/nuttx-apps.git
synced 2026-08-01 20:29:00 +00:00
fsutils/flashtool: add flashtool command support
Introducing flashtool command with following capabilities: - Flash geometry information display - Bad blocks checking - Page contents read/write - Block erase - Full flash erase Signed-off-by: zhengyu9 <zhengyu9@xiaomi.com>
This commit is contained in:
parent
8856a587a6
commit
b78ab0c6e8
5 changed files with 483 additions and 0 deletions
24
fsutils/flashtool/CMakeLists.txt
Normal file
24
fsutils/flashtool/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
# ##############################################################################
|
||||
# apps/fsutils/flashtool/CMakeLists.txt
|
||||
#
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more contributor
|
||||
# license agreements. See the NOTICE file distributed with this work for
|
||||
# additional information regarding copyright ownership. The ASF licenses this
|
||||
# file to you under the Apache License, Version 2.0 (the "License"); you may not
|
||||
# use this file except in compliance with the License. You may obtain a copy of
|
||||
# the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations under
|
||||
# the License.
|
||||
#
|
||||
# ##############################################################################
|
||||
|
||||
if(CONFIG_FSUTILS_FLASHTOOL)
|
||||
nuttx_add_application(MODULE ${CONFIG_FSUTILS_FLASHTOOL} NAME flashtool SRCS
|
||||
flashtool_main.c)
|
||||
endif()
|
||||
29
fsutils/flashtool/Kconfig
Normal file
29
fsutils/flashtool/Kconfig
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
#
|
||||
# For a description of the syntax of this configuration file,
|
||||
# see the file kconfig-language.txt in the NuttX tools repository.
|
||||
#
|
||||
|
||||
config FSUTILS_FLASHTOOL
|
||||
tristate "FLASH Tool Command"
|
||||
default n
|
||||
depends on MTD
|
||||
depends on BCH
|
||||
---help---
|
||||
Enable support for the FLASH tool.
|
||||
|
||||
if FSUTILS_FLASHTOOL
|
||||
|
||||
config FSUTILS_FLASHTOOL_STACKSIZE
|
||||
int "flashtool stack size"
|
||||
default DEFAULT_TASK_STACKSIZE
|
||||
---help---
|
||||
This is the stack size that will be used when starting the flashtool.
|
||||
|
||||
config FSUTILS_FLASHTOOL_PRIORITY
|
||||
int "flashtool priority"
|
||||
default 100
|
||||
---help---
|
||||
This is the task priority that will be used when starting the flashtool.
|
||||
|
||||
endif
|
||||
|
||||
24
fsutils/flashtool/Make.defs
Normal file
24
fsutils/flashtool/Make.defs
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
############################################################################
|
||||
# apps/fsutils/flashtool/Make.defs
|
||||
#
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership. The
|
||||
# ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance with the
|
||||
# License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
############################################################################
|
||||
|
||||
ifneq ($(CONFIG_FSUTILS_FLASHTOOL),)
|
||||
CONFIGURED_APPS += $(APPDIR)/fsutils/flashtool
|
||||
endif
|
||||
|
||||
33
fsutils/flashtool/Makefile
Normal file
33
fsutils/flashtool/Makefile
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
############################################################################
|
||||
# apps/fsutils/flashtool/Makefile
|
||||
#
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership. The
|
||||
# ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance with the
|
||||
# License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
############################################################################
|
||||
|
||||
include $(APPDIR)/Make.defs
|
||||
|
||||
# flashtool Application
|
||||
|
||||
PROGNAME = flashtool
|
||||
PRIORITY = SCHED_PRIORITY_DEFAULT
|
||||
STACKSIZE = $(CONFIG_DEFAULT_TASK_STACKSIZE)
|
||||
MODULE = $(CONFIG_FSUTILS_FLASHTOOL)
|
||||
|
||||
MAINSRC = flashtool_main.c
|
||||
|
||||
include $(APPDIR)/Application.mk
|
||||
|
||||
373
fsutils/flashtool/flashtool_main.c
Normal file
373
fsutils/flashtool/flashtool_main.c
Normal file
|
|
@ -0,0 +1,373 @@
|
|||
/****************************************************************************
|
||||
* apps/fsutils/flashtool/flashtool_main.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <nuttx/mtd/mtd.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <getopt.h>
|
||||
#include <fcntl.h>
|
||||
#include <debug.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
enum opr_list
|
||||
{
|
||||
HELP, DEVICE_INFO, READ_PAGE, WRITE_PAGE, ERASE_BLOCK, ERASE_ALL,
|
||||
CHECK_BAD_BLOCK
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
static void display_help(void)
|
||||
{
|
||||
printf("Usage : flashtool [OPTION [ARG]] device_name ...\n");
|
||||
printf("-h show this help statement\n");
|
||||
printf("-i display device geometry information\n");
|
||||
printf("-r <page> read the specified pages\n");
|
||||
printf("-w <page> write the specified pages\n");
|
||||
printf("-e <block> erase the specified blocks\n");
|
||||
printf("-n <num> number of pages or blocks\n");
|
||||
printf("-f <file> file name for read or write\n");
|
||||
printf("-b <block> check whether <block> is bad\n");
|
||||
printf("-c erase all of the flash\n");
|
||||
printf("-d <device> device name\n");
|
||||
}
|
||||
|
||||
static void display_device_info(FAR const struct mtd_geometry_s *geo)
|
||||
{
|
||||
printf("Size of one read/write page: %lu\n", geo->blocksize);
|
||||
printf("Size of one erase block: %lu\n", geo->erasesize);
|
||||
printf("Number of erase blocks: %lu\n", geo->neraseblocks);
|
||||
}
|
||||
|
||||
static int read_page(int fd, FAR const struct mtd_geometry_s *geo,
|
||||
off_t start_page, size_t npages)
|
||||
{
|
||||
FAR unsigned char *buf;
|
||||
ssize_t ret = OK;
|
||||
off_t seek;
|
||||
size_t i;
|
||||
|
||||
buf = malloc(geo->blocksize);
|
||||
if (!buf)
|
||||
{
|
||||
printf("ERROR: read_page cannot allocate memory %d\n", geo->blocksize);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
seek = geo->blocksize * start_page;
|
||||
if (lseek(fd, seek, SEEK_SET) != seek)
|
||||
{
|
||||
printf("ERROR: Cannot seek mtd to offset %lld: %d", seek, errno);
|
||||
goto oops;
|
||||
}
|
||||
|
||||
printf("Flash pages contents:\n");
|
||||
for (i = 0; i < npages; i++)
|
||||
{
|
||||
ret = read(fd, buf, geo->blocksize);
|
||||
if (ret < 0)
|
||||
{
|
||||
printf("ERROR: Read error: %d!\n", errno);
|
||||
goto oops;
|
||||
}
|
||||
|
||||
printf("Flash page %lld:\n", start_page + i);
|
||||
lib_dumpbuffer(NULL, buf, ret);
|
||||
}
|
||||
|
||||
oops:
|
||||
free(buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Write npages data from img to flash
|
||||
* If size of img is less than npags, only write img size
|
||||
*/
|
||||
|
||||
static int write_page(int fd, FAR const struct mtd_geometry_s *geo,
|
||||
off_t start_page, size_t npages, FAR const char *img)
|
||||
{
|
||||
FAR unsigned char *buf;
|
||||
off_t imglen;
|
||||
off_t seek;
|
||||
off_t i;
|
||||
int fd_src;
|
||||
int ret = OK;
|
||||
|
||||
if (img == NULL)
|
||||
{
|
||||
printf("ERROR: Need source file path!\n");
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
printf("Write data from %s...\n", img);
|
||||
seek = geo->blocksize * start_page;
|
||||
if (lseek(fd, seek, SEEK_SET) != seek)
|
||||
{
|
||||
printf("ERROR: cannot seek mtd to offset %lld: %d", seek, errno);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
fd_src = open(img, O_RDONLY);
|
||||
if (fd_src < 0)
|
||||
{
|
||||
printf("ERROR: Open file %s failed: %d\n", img, errno);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
imglen = lseek(fd_src, 0, SEEK_END);
|
||||
if (lseek(fd_src, 0, SEEK_SET) != 0)
|
||||
{
|
||||
close(fd_src);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/* Malloc a size of page for buf */
|
||||
|
||||
buf = malloc(geo->blocksize);
|
||||
if (!buf)
|
||||
{
|
||||
printf("ERROR: write_page cannot allocate memory %d\n",
|
||||
geo->blocksize);
|
||||
close(fd_src);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
for (i = start_page; i < start_page + npages; i++)
|
||||
{
|
||||
ret = read(fd_src, buf,
|
||||
(imglen < geo->blocksize) ? imglen : geo->blocksize);
|
||||
if (ret < 0)
|
||||
{
|
||||
printf("ERROR: read source file error: %d!\n", errno);
|
||||
goto oops;
|
||||
}
|
||||
|
||||
ret = write(fd, buf, geo->blocksize);
|
||||
if (ret < 0)
|
||||
{
|
||||
printf("ERROR: write error: %d!\n", errno);
|
||||
goto oops;
|
||||
}
|
||||
|
||||
imglen -= geo->blocksize;
|
||||
if (imglen <= 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
oops:
|
||||
close(fd_src);
|
||||
free(buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int erase_block(int fd, off_t start_block,
|
||||
size_t nblocks)
|
||||
{
|
||||
struct mtd_erase_s erase;
|
||||
int ret;
|
||||
|
||||
printf("Erase block from %lld to %lld!\n", start_block,
|
||||
start_block + nblocks -1);
|
||||
erase.startblock = start_block;
|
||||
erase.nblocks = nblocks;
|
||||
ret = ioctl(fd, MTDIOC_ERASESECTORS, &erase);
|
||||
if (ret < 0)
|
||||
{
|
||||
printf("ERROR: Erase failed: %d!\n", errno);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int erase_all(int fd)
|
||||
{
|
||||
if (ioctl(fd, MTDIOC_BULKERASE, 0) < 0)
|
||||
{
|
||||
printf("ERROR: MTD ioctl(MTDIOC_BULKERASE) failed: %d\n", errno);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int check_bad_block(int fd, FAR const struct mtd_geometry_s *geo)
|
||||
{
|
||||
struct mtd_bad_block_s bad_block;
|
||||
int flag = 0;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
printf("Check bad blocks in flash......\n");
|
||||
for (i = 0; i < geo->neraseblocks; i++)
|
||||
{
|
||||
bad_block.block_num = i;
|
||||
ret = ioctl(fd, MTDIOC_ISBAD, &bad_block);
|
||||
if (ret != OK)
|
||||
{
|
||||
printf("ERROR: MTDIOC_ISBAD failed: %d!\n", errno);
|
||||
return ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (bad_block.bad_flag)
|
||||
{
|
||||
printf("Block %d is bad!\n", i);
|
||||
flag = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (flag == 0)
|
||||
{
|
||||
printf("No bad blocks!\n");
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
int main(int argc, FAR char *argv[])
|
||||
{
|
||||
FAR char *mtddev = NULL;
|
||||
FAR char *img = NULL;
|
||||
struct mtd_geometry_s geo;
|
||||
enum opr_list opr = HELP;
|
||||
off_t npages = 1;
|
||||
off_t start;
|
||||
int option;
|
||||
int mode = O_RDONLY;
|
||||
int fd;
|
||||
int ret;
|
||||
|
||||
while ((option = getopt(argc, argv, ":hir:w:e:n:f:bcd:")) != -1)
|
||||
{
|
||||
switch (option)
|
||||
{
|
||||
case 'h':
|
||||
display_help();
|
||||
exit(0);
|
||||
case 'i':
|
||||
opr = DEVICE_INFO;
|
||||
break;
|
||||
case 'r':
|
||||
opr = READ_PAGE;
|
||||
start = strtoul(optarg, NULL, 0);
|
||||
break;
|
||||
case 'w':
|
||||
opr = WRITE_PAGE;
|
||||
mode = O_RDWR;
|
||||
start = strtoul(optarg, NULL, 0);
|
||||
break;
|
||||
case 'e':
|
||||
opr = ERASE_BLOCK;
|
||||
start = strtoul(optarg, NULL, 0);
|
||||
break;
|
||||
case 'n':
|
||||
npages = strtoul(optarg, NULL, 0);
|
||||
break;
|
||||
case 'f':
|
||||
img = optarg;
|
||||
break;
|
||||
case 'b':
|
||||
opr = CHECK_BAD_BLOCK;
|
||||
break;
|
||||
case 'c':
|
||||
opr = ERASE_ALL;
|
||||
break;
|
||||
case 'd':
|
||||
mtddev = optarg;
|
||||
break;
|
||||
case ':':
|
||||
printf("Error: Missing required argument\n");
|
||||
exit(1);
|
||||
case '?':
|
||||
printf("Error: Unrecognized option\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (mtddev == NULL)
|
||||
{
|
||||
printf("Error: Device name is required!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
fd = open(mtddev, mode, 0777);
|
||||
if (fd < 0)
|
||||
{
|
||||
printf("ERROR: Failed to open '%s': %d\n", mtddev, errno);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = ioctl(fd, MTDIOC_GEOMETRY, &geo);
|
||||
if (ret < 0)
|
||||
{
|
||||
printf("ERROR: Ioctl MTDIOC_GEOMETRY failed: %d\n", errno);
|
||||
goto oops;
|
||||
}
|
||||
|
||||
switch (opr)
|
||||
{
|
||||
case DEVICE_INFO:
|
||||
display_device_info(&geo);
|
||||
break;
|
||||
case READ_PAGE:
|
||||
ret = read_page(fd, &geo, start, npages);
|
||||
break;
|
||||
case WRITE_PAGE:
|
||||
ret = write_page(fd, &geo, start, npages, img);
|
||||
break;
|
||||
case ERASE_BLOCK:
|
||||
ret = erase_block(fd, start, npages);
|
||||
break;
|
||||
case ERASE_ALL:
|
||||
ret = erase_all(fd);
|
||||
break;
|
||||
case CHECK_BAD_BLOCK:
|
||||
ret = check_bad_block(fd, &geo);
|
||||
break;
|
||||
default:
|
||||
}
|
||||
|
||||
oops:
|
||||
close(fd);
|
||||
return ret;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue