From: Sascha Hauer <s.hauer@pengutronix.de>
To: Barebox List <barebox@lists.infradead.org>
Subject: [PATCH 09/12] partitions: implement partition manipulation support
Date: Mon, 19 Feb 2024 09:31:37 +0100 [thread overview]
Message-ID: <20240219083140.2713047-10-s.hauer@pengutronix.de> (raw)
In-Reply-To: <20240219083140.2713047-1-s.hauer@pengutronix.de>
This adds a function API to manipulate partition tables. Basically
partition_table_new() and partition_table_read() are factored out from
existing code. Apart from that we will have partition_create() to
create a new partition and partition_remove() to remove a partition.
These functions do basic sanity checks like partition overlap checking,
access beyond device cheks and call into not yet existing efi or msdos
specific function hooks.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
common/Kconfig | 3 +
common/partitions.c | 156 ++++++++++++++++++++++++++++++++++++-------
include/partitions.h | 22 ++++++
3 files changed, 157 insertions(+), 24 deletions(-)
diff --git a/common/Kconfig b/common/Kconfig
index ddca1e913b..d16c8696da 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -841,6 +841,9 @@ config PARTITION
bool
prompt "Enable Partitions"
+config PARTITION_MANIPULATION
+ bool
+
source "common/partitions/Kconfig"
config ENV_HANDLING
diff --git a/common/partitions.c b/common/partitions.c
index abbe31ed11..7bcd0973b8 100644
--- a/common/partitions.c
+++ b/common/partitions.c
@@ -102,6 +102,133 @@ static struct partition_parser *partition_parser_get_by_filetype(uint8_t *buf)
return NULL;
}
+struct partition_desc *partition_table_new(struct block_device *blk, const char *type)
+{
+ struct partition_desc *pdesc;
+ struct partition_parser *parser;
+
+ list_for_each_entry(parser, &partition_parser_list, list) {
+ if (!strcmp(parser->name, type))
+ goto found;
+ }
+
+ pr_err("Cannot find partition parser \"%s\"\n", type);
+
+ return ERR_PTR(-ENOSYS);
+
+found:
+ pdesc = parser->create(blk);
+ if (IS_ERR(pdesc))
+ return ERR_CAST(pdesc);
+
+ pdesc->parser = parser;
+
+ return pdesc;
+}
+
+struct partition_desc *partition_table_read(struct block_device *blk)
+{
+ struct partition_parser *parser;
+ struct partition_desc *pdesc = NULL;
+ uint8_t *buf;
+ int ret;
+
+ buf = malloc(2 * SECTOR_SIZE);
+
+ ret = block_read(blk, buf, 0, 2);
+ if (ret != 0) {
+ dev_err(blk->dev, "Cannot read MBR/partition table: %pe\n", ERR_PTR(ret));
+ goto err;
+ }
+
+ parser = partition_parser_get_by_filetype(buf);
+ if (!parser)
+ goto err;
+
+ pdesc = parser->parse(buf, blk);
+ pdesc->parser = parser;
+err:
+ free(buf);
+
+ return pdesc;
+}
+
+int partition_table_write(struct partition_desc *pdesc)
+{
+ if (!pdesc->parser->write)
+ return -ENOSYS;
+
+ return pdesc->parser->write(pdesc);
+}
+
+static bool overlap(uint64_t s1, uint64_t e1, uint64_t s2, uint64_t e2)
+{
+ if (e1 < s2)
+ return false;
+ if (s1 > e2)
+ return false;
+ return true;
+}
+
+int partition_create(struct partition_desc *pdesc, const char *name,
+ const char *fs_type, uint64_t lba_start, uint64_t lba_end)
+{
+ struct partition *part;
+
+ if (!pdesc->parser->mkpart)
+ return -ENOSYS;
+
+ if (lba_end < lba_start) {
+ pr_err("lba_end < lba_start: %llu < %llu\n", lba_end, lba_start);
+ return -EINVAL;
+ }
+
+ if (lba_end >= pdesc->blk->num_blocks) {
+ pr_err("lba_end exceeds device: %llu >= %llu\n", lba_end, pdesc->blk->num_blocks);
+ return -EINVAL;
+ }
+
+ list_for_each_entry(part, &pdesc->partitions, list) {
+ if (overlap(part->first_sec,
+ part->first_sec + part->size - 1,
+ lba_start, lba_end)) {
+ pr_err("new partition %llu-%llu overlaps with partition %s (%llu-%llu)\n",
+ lba_start, lba_end, part->name, part->first_sec,
+ part->first_sec + part->size - 1);
+ return -EINVAL;
+ }
+ }
+
+ return pdesc->parser->mkpart(pdesc, name, fs_type, lba_start, lba_end);
+}
+
+int partition_remove(struct partition_desc *pdesc, int num)
+{
+ struct partition *part;
+
+ if (!pdesc->parser->rmpart)
+ return -ENOSYS;
+
+ list_for_each_entry(part, &pdesc->partitions, list) {
+ if (part->num == num)
+ return pdesc->parser->rmpart(pdesc, part);
+ }
+
+ pr_err("Partition %d doesn't exist\n", num);
+ return -ENOENT;
+}
+
+void partition_table_free(struct partition_desc *pdesc)
+{
+ pdesc->parser->partition_free(pdesc);
+}
+
+void partition_desc_init(struct partition_desc *pd, struct block_device *blk)
+{
+ pd->blk = blk;
+ INIT_LIST_HEAD(&pd->partitions);
+}
+
/**
* Try to collect partition information on the given block device
* @param blk Block device to examine
@@ -111,31 +238,14 @@ static struct partition_parser *partition_parser_get_by_filetype(uint8_t *buf)
*/
int parse_partition_table(struct block_device *blk)
{
- struct partition_desc *pdesc = NULL;
int i;
int rc = 0;
- struct partition_parser *parser;
struct partition *part;
- uint8_t *buf;
-
- buf = malloc(2 * SECTOR_SIZE);
+ struct partition_desc *pdesc;
- rc = block_read(blk, buf, 0, 2);
- if (rc != 0) {
- dev_err(blk->dev, "Cannot read MBR/partition table: %pe\n", ERR_PTR(rc));
- goto on_error;
- }
-
- parser = partition_parser_get_by_filetype(buf);
- if (!parser)
- goto on_error;
-
- pdesc = parser->parse(buf, blk);
+ pdesc = partition_table_read(blk);
if (!pdesc)
- goto on_error;
-
- if (list_empty(&pdesc->partitions))
- goto on_error;
+ return 0;
/* at least one partition description found */
list_for_each_entry(part, &pdesc->partitions, list) {
@@ -148,10 +258,8 @@ int parse_partition_table(struct block_device *blk)
rc = 0;
}
-on_error:
- free(buf);
- if (pdesc)
- parser->partition_free(pdesc);
+ partition_table_free(pdesc);
+
return rc;
}
diff --git a/include/partitions.h b/include/partitions.h
index ab593109e6..b5379db92a 100644
--- a/include/partitions.h
+++ b/include/partitions.h
@@ -28,18 +28,40 @@ struct partition {
int num;
};
+struct partition_parser;
+
struct partition_desc {
struct list_head partitions;
+ struct partition_parser *parser;
+ struct block_device *blk;
};
struct partition_parser {
struct partition_desc *(*parse)(void *buf, struct block_device *blk);
void (*partition_free)(struct partition_desc *pd);
+ struct partition_desc *(*create)(struct block_device *blk);
+ int (*mkpart)(struct partition_desc *pd, const char *name, const char *fs_type,
+ uint64_t start, uint64_t end);
+ int (*rmpart)(struct partition_desc *pd, struct partition *part);
+ int (*write)(struct partition_desc *pd);
+ int (*rename)(struct partition *part, const char *name);
+ int (*setguid)(struct partition *part, guid_t *guid);
enum filetype type;
struct list_head list;
+
+ const char *name;
};
+void partition_desc_init(struct partition_desc *pd, struct block_device *blk);
int partition_parser_register(struct partition_parser *p);
+struct partition_desc *partition_table_read(struct block_device *blk);
+struct partition_desc *partition_table_new(struct block_device *blk, const char *type);
+int partition_table_write(struct partition_desc *pdesc);
+int partition_create(struct partition_desc *pdesc, const char *name,
+ const char *fs_type, uint64_t lba_start, uint64_t lba_end);
+int partition_remove(struct partition_desc *pdesc, int num);
+void partition_table_free(struct partition_desc *pdesc);
+
#endif /* __PARTITIONS_PARSER_H__ */
--
2.39.2
next prev parent reply other threads:[~2024-02-19 8:32 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-02-19 8:31 [PATCH 00/12] Partition table " Sascha Hauer
2024-02-19 8:31 ` [PATCH 01/12] partitions: dos: save indention level Sascha Hauer
2024-02-19 8:31 ` [PATCH 02/12] partition: allocate struct partition_desc in parser Sascha Hauer
2024-02-19 8:31 ` [PATCH 03/12] partition: allocate struct partition " Sascha Hauer
2024-02-19 8:31 ` [PATCH 04/12] partition: efi: keep raw data Sascha Hauer
2024-02-19 8:31 ` [PATCH 05/12] uuid: implement random uuid/guid Sascha Hauer
2024-02-19 8:31 ` [PATCH 06/12] linux/sizes.h: add more defines Sascha Hauer
2024-02-19 8:31 ` [PATCH 07/12] partition: add PARTITION_LINUX_DATA_GUID define Sascha Hauer
2024-02-19 8:31 ` [PATCH 08/12] partitions: move parser.h to include/partitions.h Sascha Hauer
2024-02-19 8:31 ` Sascha Hauer [this message]
2024-02-19 8:31 ` [PATCH 10/12] partitions: dos: implement partition manipulation support Sascha Hauer
2024-02-28 17:37 ` Ahmad Fatoum
2024-02-29 7:16 ` Sascha Hauer
2024-02-19 8:31 ` [PATCH 11/12] partitions: efi: " Sascha Hauer
2024-02-28 17:36 ` Ahmad Fatoum
2024-02-19 8:31 ` [PATCH 12/12] commands: add parted Sascha Hauer
2024-02-19 9:38 ` Ulrich Ölmann
2024-02-20 10:47 ` [PATCH 00/12] Partition table manipulation support Sascha Hauer
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20240219083140.2713047-10-s.hauer@pengutronix.de \
--to=s.hauer@pengutronix.de \
--cc=barebox@lists.infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox