mirror of
https://github.com/openharmony/third_party_mtd_utils.git
synced 2026-07-18 21:04:32 -04:00
194 lines
4.4 KiB
C
194 lines
4.4 KiB
C
/*
|
|
* mtdpart.c
|
|
*
|
|
* Copyright 2015 The Chromium OS Authors.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* Overview:
|
|
* This utility adds or removes a partition from an MTD device.
|
|
*/
|
|
|
|
#define PROGRAM_NAME "mtdpart"
|
|
|
|
#include <fcntl.h>
|
|
#include <getopt.h>
|
|
#include <limits.h>
|
|
#include <linux/blkpg.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <sys/ioctl.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/types.h>
|
|
#include <unistd.h>
|
|
|
|
#include "common.h"
|
|
|
|
static void display_help(int status)
|
|
{
|
|
fprintf(status == EXIT_SUCCESS ? stdout : stderr,
|
|
"Usage: %1$s add [OPTION] <MTD_DEVICE> <PART_NAME> <START> <SIZE>\n"
|
|
" %1$s del [OPTION] <MTD_DEVICE> <PART_NUMBER>\n"
|
|
"Adds a partition to an MTD device, or remove an existing partition from it.\n"
|
|
"\n"
|
|
" -h, --help Display this help and exit\n"
|
|
" -V, --version Output version information and exit\n"
|
|
"\n"
|
|
"START location and SIZE of the partition are in bytes. They should align on\n"
|
|
"eraseblock size.\n",
|
|
PROGRAM_NAME
|
|
);
|
|
exit(status);
|
|
}
|
|
|
|
static void display_version(void)
|
|
{
|
|
common_print_version();
|
|
printf("%1$s comes with NO WARRANTY\n"
|
|
"to the extent permitted by law.\n"
|
|
"\n"
|
|
"You may redistribute copies of %1$s\n"
|
|
"under the terms of the GNU General Public Licence.\n"
|
|
"See the file `COPYING' for more information.\n",
|
|
PROGRAM_NAME);
|
|
exit(EXIT_SUCCESS);
|
|
}
|
|
|
|
/* Command arguments */
|
|
|
|
typedef enum {
|
|
COMMAND_ADD,
|
|
COMMAND_DEL
|
|
} command_type;
|
|
|
|
static command_type command; /* add or del */
|
|
static const char *mtddev; /* mtd device name */
|
|
static const char *part_name; /* partition name */
|
|
static int part_no; /* partition number */
|
|
static long long start_addr; /* start address */
|
|
static long long length; /* partition size */
|
|
|
|
static void process_options(int argc, char * const argv[])
|
|
{
|
|
int error = 0;
|
|
|
|
for (;;) {
|
|
int option_index = 0;
|
|
static const char short_options[] = "hV";
|
|
static const struct option long_options[] = {
|
|
{"version", no_argument, 0, 'V'},
|
|
{"help", no_argument, 0, 'h'},
|
|
{0, 0, 0, 0},
|
|
};
|
|
|
|
int c = getopt_long(argc, argv, short_options,
|
|
long_options, &option_index);
|
|
if (c == EOF) {
|
|
break;
|
|
}
|
|
|
|
switch (c) {
|
|
case 'V':
|
|
display_version();
|
|
break;
|
|
case 'h':
|
|
display_help(EXIT_SUCCESS);
|
|
break;
|
|
case '?':
|
|
error++;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ((argc - optind) < 3 || error)
|
|
display_help(EXIT_FAILURE);
|
|
|
|
const char *s_command = argv[optind++];
|
|
mtddev = argv[optind++];
|
|
|
|
if (strcmp(s_command, "del") == 0 && (argc - optind) == 1) {
|
|
const char *s_part_no = argv[optind++];
|
|
|
|
long tmp = simple_strtol(s_part_no, &error);
|
|
if (tmp < 0)
|
|
errmsg_die("Can't specify negative partition number: %ld",
|
|
tmp);
|
|
if (tmp > INT_MAX)
|
|
errmsg_die("Partition number exceeds INT_MAX: %ld",
|
|
tmp);
|
|
|
|
part_no = tmp;
|
|
command = COMMAND_DEL;
|
|
} else if (strcmp(s_command, "add") == 0 && (argc - optind) == 3) {
|
|
const char *s_start;
|
|
const char *s_length;
|
|
|
|
part_name = argv[optind++];
|
|
s_start = argv[optind++];
|
|
s_length = argv[optind++];
|
|
|
|
if (strlen(part_name) >= BLKPG_DEVNAMELTH)
|
|
errmsg_die("Partition name (%s) should be less than %d characters",
|
|
part_name, BLKPG_DEVNAMELTH);
|
|
|
|
start_addr = simple_strtoll(s_start, &error);
|
|
if (start_addr < 0)
|
|
errmsg_die("Can't specify negative start offset: %lld",
|
|
start_addr);
|
|
|
|
length = simple_strtoll(s_length, &error);
|
|
if (length < 0)
|
|
errmsg_die("Can't specify negative length: %lld",
|
|
length);
|
|
|
|
command = COMMAND_ADD;
|
|
} else
|
|
display_help(EXIT_FAILURE);
|
|
|
|
if (error)
|
|
display_help(EXIT_FAILURE);
|
|
}
|
|
|
|
|
|
int main(int argc, char * const argv[])
|
|
{
|
|
int fd;
|
|
struct blkpg_partition part;
|
|
struct blkpg_ioctl_arg arg;
|
|
|
|
process_options(argc, argv);
|
|
|
|
fd = open(mtddev, O_RDWR | O_CLOEXEC);
|
|
if (fd == -1)
|
|
sys_errmsg_die("Cannot open %s", mtddev);
|
|
|
|
memset(&part, 0, sizeof(part));
|
|
|
|
memset(&arg, 0, sizeof(arg));
|
|
arg.datalen = sizeof(part);
|
|
arg.data = ∂
|
|
|
|
switch (command) {
|
|
case COMMAND_ADD:
|
|
part.start = start_addr;
|
|
part.length = length;
|
|
strncpy(part.devname, part_name, sizeof(part.devname));
|
|
arg.op = BLKPG_ADD_PARTITION;
|
|
break;
|
|
case COMMAND_DEL:
|
|
part.pno = part_no;
|
|
arg.op = BLKPG_DEL_PARTITION;
|
|
break;
|
|
}
|
|
|
|
if (ioctl(fd, BLKPG, &arg))
|
|
sys_errmsg_die("Failed to issue BLKPG ioctl");
|
|
|
|
close(fd);
|
|
|
|
/* Exit happy */
|
|
return EXIT_SUCCESS;
|
|
}
|