Patchwork [1/1,MTD-UTILS] Adding run-time mtd partitioning utility

login
register
mail settings
Submitter Rohit Hassan Sathyanarayan
Date July 29, 2010, 11:30 a.m.
Message ID <000001cb2f11$85fb9cc0$91f2d640$%hs@samsung.com>
Download mbox | patch
Permalink /patch/60224/
State New
Headers show

Comments

Rohit Hassan Sathyanarayan - July 29, 2010, 11:30 a.m.
Hi All

Sending the patch on mtd-utils for run-time partitioning utility.



Signed-off-by: Rohit HS <rohit.hs@samsung.com>
---
Makefile                |    1
include/mtd/mtd-abi.h   |   16 +
mtd_runtime_partition.c |  389 ++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 406 insertions(+)

---
Artem Bityutskiy - Aug. 23, 2010, 2:37 p.m.
On Thu, 2010-07-29 at 17:00 +0530, Rohit Hassan Sathyanarayan wrote:
> Hi All
> 
> Sending the patch on mtd-utils for run-time partitioning utility.
> 
> 
> 
> Signed-off-by: Rohit HS <rohit.hs@samsung.com>

Not taking this so far. Let's first create proper and mergeble kernel
implementation first, then will add the user-space utility, ok?

Patch

diff --git a/Makefile b/Makefile
index d315f39..bfa2c45 100644
--- a/Makefile
+++ b/Makefile
@@ -16,6 +16,7 @@  TARGETS = ftl_format flash_erase flash_eraseall nanddump doc_loadbios \
 	nftldump nftl_format docfdisk \
 	rfddump rfdformat \
 	serve_image recv_image \
+	mtd_runtime_partition \
 	sumtool #jffs2reader
 
 SYMLINKS =
diff --git a/include/mtd/mtd-abi.h b/include/mtd/mtd-abi.h
index c6954ed..22ba713 100644
--- a/include/mtd/mtd-abi.h
+++ b/include/mtd/mtd-abi.h
@@ -30,6 +30,18 @@  struct mtd_oob_buf64 {
 	__u64 usr_ptr;
 };
 
+struct user_mtd {
+	char name[32];
+	 __u64 partition_size;
+	 __u64 partition_offset;
+	 __u32 partition_mask;
+};
+
+struct user_mtd_info {
+	struct user_mtd *pst_user_partitions;
+	__u32 num_partitions;
+};
+
 #define MTD_ABSENT		0
 #define MTD_RAM			1
 #define MTD_ROM			2
@@ -110,6 +122,10 @@  struct otp_info {
 #define MEMERASE64		_IOW('M', 20, struct erase_info_user64)
 #define MEMWRITEOOB64		_IOWR('M', 21, struct mtd_oob_buf64)
 #define MEMREADOOB64		_IOWR('M', 22, struct mtd_oob_buf64)
+#define MTDPARTITIONCREATE      _IOW('M', 23, int)
+#define MTDPARTITIONDELETE      _IOW('M', 24, int)
+#define MTDPARTITIONSETPERMISSION _IOW('M', 26, int)
+#define MTDPARTITIONMERGE       _IOW('M', 27, int)
 
 /*
  * Obsolete legacy interface. Keep it in order not to break userspace
diff --git a/mtd_runtime_partition.c b/mtd_runtime_partition.c
new file mode 100644
index 0000000..a639563
--- /dev/null
+++ b/mtd_runtime_partition.c
@@ -0,0 +1,389 @@ 
+/*======================================================================
+	mtd_runtime_partition.c: Run-Time Partitioning Support Utility
+	(C) Copyright 2009-2010
+	Samsung Electronics, <www.samsung.com>
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation; either version 2 of the License, or
+	(at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+
+	This is utility for run-time partitioning support in MTD
+	Usage:
+	#mtdpart-h
+	Options
+		c -- Create Partition
+		d -- Delete Partition
+		j -- Merge adjacent Partition
+		p -- Set Partition Permission
+			ro  -> ReadOnly Permission
+			wr -> WriteRead Permission
+
+======================================================================*/
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <time.h>
+#include <sys/ioctl.h>
+#include <sys/mount.h>
+#include <mtd/mtd-user.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+
+#define MTD_NUMBER_DIGITS	(2)
+#define MTD_READWRITE		(0)
+#define MAX_ALLOWED		(4)
+
+#undef DEBUG
+#ifdef DEBUG
+#define dbg(x) printf x
+#else
+#define dbg(x)
+#endif
+
+#define PARTITION_INVALID		(0)
+#define PARTITION_SIZE_NOTALIGNED	(1)
+#define PARTITION_VALID			(2)
+
+struct user_mtd_info user_mtd_data;
+static const char s_entry_node[] = "/dev/mtd0";
+static const char s_mtd_to_partition[16];
+static uint64_t u64_mtd_erase_size;
+/*
+*  NAME        : get_mag
+*  DESCRIPTION : Converts string to hex.
+*  PARAMS:
+*  Input::    p8_buf :Char pointer to buffer.
+*  Return value:: Converted Hex number.
+*
+*/
+static uint64_t get_mag(char *p8_buf)
+{
+	int j = 0;
+	uint64_t temp = 0;
+	uint64_t data = 0;
+	int count = 0;
+
+	while (1) {
+		if (p8_buf[count] == 0xff)
+			break;
+		count++;
+	}
+	count -= 2;
+	while (count >= 0) {
+		if ((p8_buf[count] >= '0') && (p8_buf[count] <= '9')) {
+			temp = p8_buf[count] - '0';
+			data |= (temp << (j*4));
+		} else if ((p8_buf[count] >= 'a') && (p8_buf[count] <= 'f')) {
+			temp = (p8_buf[count] - 'a') + 10;
+			data |= (temp << (j*4));
+		}
+	j++;
+	count--;
+	}
+	return data;
+}
+
+/*
+*  NAME        : partition_help
+*  DESCRIPTION : This is help function for syntax.
+*  PARAMS:
+*  Input::    None.
+*  Return value: None.
+*
+*/
+static void partition_help(void)
+{
+	fprintf(stderr, "Options\n"
+		"=======================================================\n"
+		"\r c -- Create Partition\n"
+		"\r d -- Delete Partition\n"
+		"\r j -- Merge adjacent Partition\n"
+		"\r p -- Set Partition Permission\n"
+		"         ro  -> ReadOnly Permission\n"
+		"         wr -> WriteRead Permission\n"
+		"=======================================================\n");
+	exit(0);
+}
+/*
+ * NAME        : get_mtd_number
+ * DESCRIPTION : This Function gives mtd device number from mtd device node.
+ * PARAMS:
+ * Input:: p8_ptr: Char pointer to mtd device name.
+ * Return value: MTD Device Number.
+ *
+*/
+static int get_mtd_number(char *p8_ptr)
+{
+	char temp[2] = {0};
+	int i = 0;
+	int dummy = 0;
+
+	while (*p8_ptr++ != 0)
+		dummy = 0;
+	--p8_ptr;
+	for (i = MTD_NUMBER_DIGITS-1; i >= 0; i--) {
+		--p8_ptr;
+		if ((*p8_ptr >= '0') && (*p8_ptr <= '9'))
+			temp[i] = *p8_ptr;
+	}
+	if (temp[0] == 0) {
+		temp[0] = temp[MTD_NUMBER_DIGITS-1];
+		temp[MTD_NUMBER_DIGITS-1] = 0;
+	}
+	i = -1;
+	i = (int)atoi(temp);
+	return i;
+}
+/*
+*  NAME        : get_partition_data
+*  DESCRIPTION : This Function parses MTD user Partition and updates.
+*  PARAMS:
+*    Input::	None.
+*    Return value: None.
+*
+*/
+static void get_partition_data(void)
+{
+	char temp = 0;
+	int index = 0;
+	char partition_name[32];
+	char buffer[16];
+	struct user_mtd *ptr_pdata;
+	char mask_flags[2];
+
+	fprintf(stdout, "Enter number of Partitions to create\n");
+	fscanf(stdin, "%c", &temp);
+	user_mtd_data.num_partitions = (int)atoi(&temp);
+
+	if (user_mtd_data.num_partitions <= 0) {
+		fprintf(stderr, "Error in number of Partitions\n");
+		exit(0);
+	}
+	user_mtd_data.pst_user_partitions = malloc(sizeof(struct user_mtd)*
+						user_mtd_data.num_partitions);
+	ptr_pdata = user_mtd_data.pst_user_partitions;
+	if (user_mtd_data.pst_user_partitions == NULL) {
+		fprintf(stderr, "Unable to allocate memory\n");
+		exit(0);
+	}
+
+	for (index = 0; index < user_mtd_data.num_partitions; index++) {
+		/*Get MTD Partition name*/
+		fprintf(stdout, "Enter Partition %d data\n", index+1);
+		fprintf(stdout, "=======================\n");
+		fprintf(stdout, "Enter Partition name\n");
+		fscanf(stdin, "%s", partition_name);
+		memcpy(ptr_pdata->name, partition_name, 32);
+		/*Get MTD Partition offset*/
+		fprintf(stdout, "Enter Partition Offset\n");
+		memset(buffer, 0xff, 16);
+		fscanf(stdin, "%s", buffer);
+		ptr_pdata->partition_offset =  get_mag(buffer);
+		if ((ptr_pdata->partition_offset % u64_mtd_erase_size) != 0) {
+			fprintf(stderr, "Partition offset allignmenterror\n");
+			exit(0);
+		}
+		/*Get MTD Partition Size*/
+		fprintf(stdout, "Enter Partition Size\n");
+		memset(buffer, 0xff, 16);
+		fscanf(stdin, "%s", buffer);
+		ptr_pdata->partition_size =  get_mag(buffer);
+		if (ptr_pdata->partition_size < u64_mtd_erase_size) {
+			fprintf(stderr, "Partition size < block size\n");
+			exit(0);
+		}
+		if ((ptr_pdata->partition_size % u64_mtd_erase_size) != 0) {
+			fprintf(stderr, "Partition allignment error\n");
+			exit(0);
+		}
+		/*Get MTD Partition permission*/
+		fprintf(stdout, "EnterPartitionPermission:: ro or wr\n");
+		fscanf(stdin, "%s", mask_flags);
+		if (strcmp((const char *)mask_flags, (const char*)"wr") == 0)
+			ptr_pdata->partition_mask = MTD_READWRITE;
+		else if (strcmp((const char *)mask_flags,
+				(const char *)"ro") == 0)
+			ptr_pdata->partition_mask = MTD_WRITEABLE;
+		else {
+			fprintf(stderr, "Only ro and wr allowed\n");
+			exit(0);
+		}
+		/*Get nex MTD Partition information*/
+		ptr_pdata++;
+		fprintf(stdout, "=======================\n");
+	}
+}
+/*
+*  NAME        : main
+*  DESCRIPTION : This function is the entry point for the application
+*
+*	PARAMS:
+*	Input::
+*            argv[1] : ASCII character 'c' to create Partition
+*                                      'd' to delete Partition
+*                                      'p' to set permission
+*                                      'j' to merge Partition
+*            argv[2] : Pointer to MTD device name
+*            argv[3] : Pointer to Partition Information
+*
+*  Return value: Zero on Success
+*                Error on File open.
+*
+*/
+int main(int u8_argc, char *p8_argv[])
+{
+	int i32_Fd;
+	char u8_cmd;
+	uint32_t u32_mask_flags;
+	mtd_info_t mtd_memory;
+	unsigned char merge_partitions[2];
+	int delete_part_num = -1;
+
+	if (u8_argc == 1) {
+		partition_help();
+		return -1;
+	}
+	if ((p8_argv[1][0] != 'c')
+		&& (p8_argv[1][0] != 'd')
+		&& (p8_argv[1][0] != 'p')
+		&& (p8_argv[1][0] != 'j')) {
+		partition_help();
+		return -1;
+	}
+
+	u8_cmd = p8_argv[1][0];
+	switch (u8_cmd) {
+	case 'c':
+	case 'C':
+		if (u8_argc < 3) {
+			fprintf(stderr, "Create MTD Partitions usage..\n");
+			fprintf(stderr, "mtdpart c /dev/mtd4\n");
+			exit(0);
+		}
+		i32_Fd = open(p8_argv[2], O_RDONLY);
+		if (i32_Fd < 0) {
+			fprintf(stderr, "File open error\n");
+			return -1;
+		}
+		/*Get MTD Erase size*/
+		if (ioctl(i32_Fd, MEMGETINFO, &mtd_memory) != 0) {
+			dbg(("Error in reading MTD memory data\n"));
+			return -1;
+		}
+		u64_mtd_erase_size = mtd_memory.erasesize;
+		/*Get MTD partitions from user*/
+		get_partition_data();
+		/*Create MTD partitions*/
+		if (ioctl(i32_Fd, MTDPARTITIONCREATE, &user_mtd_data) == 0)
+			dbg((" mtd partitions created\n"));
+		close(i32_Fd);
+		/*Open default mtd device*/
+		i32_Fd = open(s_entry_node, O_RDONLY);
+		if (i32_Fd < 0) {
+			fprintf(stderr, "File open error\n");
+			return -1;
+		}
+		/*Delete parent MTD device*/
+		delete_part_num = get_mtd_number(p8_argv[2]);
+		if (ioctl(i32_Fd, MTDPARTITIONDELETE, &delete_part_num) == 0)
+			dbg(("mtd partition deleted\n"));
+		close(i32_Fd);
+		break;
+	case 'd':
+	case 'D':
+		/*sanity check*/
+		if (u8_argc < 3) {
+			fprintf(stderr, "Delete MTD Partition usage..\n");
+			fprintf(stderr, "mtdpart d /dev/mtd4\n");
+			exit(0);
+		}
+		i32_Fd = open(p8_argv[2], O_RDONLY);
+		if (i32_Fd < 0) {
+			fprintf(stderr, "File open error\n");
+			return -1;
+		}
+		close(i32_Fd);
+		/*Delete user given partition*/
+		i32_Fd = open(s_entry_node, O_RDONLY);
+		if (i32_Fd < 0) {
+			fprintf(stderr, "File open error\n");
+			return -1;
+		}
+		delete_part_num = get_mtd_number(p8_argv[2]);
+		if (ioctl(i32_Fd, MTDPARTITIONDELETE, &delete_part_num) == 0)
+			fprintf(stdout, " mtd partition deleted\n");
+		else
+			fprintf(stderr, "Unable to delete Partition\n");
+		close(i32_Fd);
+		break;
+	case 'p':
+	case 'P':
+		/*sanity check*/
+		if (u8_argc < 4) {
+			fprintf(stderr, "Change Partition permission usage\n");
+			fprintf(stderr, "mtdpart p /dev/mtd4 ro|wr\n");
+			exit(0);
+		}
+		u32_mask_flags = ((0x0000FFFF) & get_mtd_number(p8_argv[2]));
+		/* Get the Permisson from user */
+		if (strcmp((const char *)p8_argv[3], (const char *)"wr") == 0) {
+			u32_mask_flags |= ((MTD_WRITEABLE << 16)&(0xFFFF0000));
+		} else if (strcmp(p8_argv[3], "ro") == 0) {
+			u32_mask_flags |= ((MTD_READWRITE << 16)&(0xFFFF0000));
+		} else {
+		fprintf(stderr, "Wrong Permission Options\n");
+		break;
+		}
+		/* Open the MTD device and set the Permission*/
+		i32_Fd = open(s_entry_node, O_RDONLY);
+		if (i32_Fd < 0) {
+			fprintf(stderr, "File open error\n");
+			return -1;
+		}
+		/*Change Partition permission*/
+		if (ioctl(i32_Fd, MTDPARTITIONSETPERMISSION, &u32_mask_flags)
+				 == 0)
+			fprintf(stdout, "Permission changed successfully\n");
+		else
+			fprintf(stderr, "set Partition Priority error\n");
+		close(i32_Fd);
+		break;
+	case 'j':
+	case 'J':
+		if (u8_argc < 4) {
+			fprintf(stderr, "Merge adjacent Partiitons usage\n");
+			fprintf(stderr, "mtdpart j /dev/mtd4 /dev/mtd5\n");
+			exit(0);
+		}
+		merge_partitions[0] = get_mtd_number(p8_argv[2]);
+		merge_partitions[1] = get_mtd_number(p8_argv[3]);
+		/*Open the MTD device and merge Partition*/
+		i32_Fd = open(s_entry_node, O_RDONLY);
+		if (i32_Fd < 0) {
+			fprintf(stderr, "File open error\n");
+			return -1;
+		}
+		/*Merge two adjacent partitions*/
+		if (0 == ioctl(i32_Fd, MTDPARTITIONMERGE, &merge_partitions))
+			fprintf(stdout, "Partitions merged successfully\n");
+		else
+			fprintf(stderr, "Unable to merge Partition\n");
+		close(i32_Fd);
+		break;
+	}
+	return 0;
+}
+
+