summaryrefslogtreecommitdiffstats
path: root/common/partitions
diff options
context:
space:
mode:
Diffstat (limited to 'common/partitions')
-rw-r--r--common/partitions/Kconfig13
-rw-r--r--common/partitions/Makefile1
-rw-r--r--common/partitions/dos.c88
-rw-r--r--common/partitions/parser.h35
4 files changed, 137 insertions, 0 deletions
diff --git a/common/partitions/Kconfig b/common/partitions/Kconfig
new file mode 100644
index 0000000000..3f81c2f922
--- /dev/null
+++ b/common/partitions/Kconfig
@@ -0,0 +1,13 @@
+config PARTITION_DISK
+ depends on PARTITION
+ bool "DISK partition support"
+ help
+ Add support for handling common partition tables on all kind of disk
+ like devices (harddisks, CF cards, SD cards and so on)
+
+config PARTITION_DISK_DOS
+ depends on PARTITION_DISK
+ default y
+ bool "DOS partition support"
+ help
+ Add support to handle partitions in DOS style.
diff --git a/common/partitions/Makefile b/common/partitions/Makefile
new file mode 100644
index 0000000000..0a5c70d16a
--- /dev/null
+++ b/common/partitions/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_PARTITION_DISK_DOS) += dos.o
diff --git a/common/partitions/dos.c b/common/partitions/dos.c
new file mode 100644
index 0000000000..4f147f72da
--- /dev/null
+++ b/common/partitions/dos.c
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2009...2011 Juergen Beisert, Pengutronix
+ *
+ * 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.
+ */
+
+#include <common.h>
+#include <disks.h>
+#include <init.h>
+#include <asm/unaligned.h>
+
+#include "parser.h"
+
+/**
+ * Guess the size of the disk, based on the partition table entries
+ * @param dev device to create partitions for
+ * @param table partition table
+ * @return sector count
+ */
+static int disk_guess_size(struct device_d *dev, struct partition_entry *table)
+{
+ uint64_t size = 0;
+ int i;
+
+ for (i = 0; i < 4; i++) {
+ if (table[i].partition_start != 0) {
+ size += get_unaligned_le32(&table[i].partition_start) - size;
+ size += get_unaligned_le32(&table[i].partition_size);
+ }
+ }
+
+ return (int)size;
+}
+
+/**
+ * Check if a DOS like partition describes this block device
+ * @param blk Block device to register to
+ * @param pd Where to store the partition information
+ *
+ * It seems at least on ARM this routine canot use temp. stack space for the
+ * sector. So, keep the malloc/free.
+ */
+static void dos_partition(void *buf, struct block_device *blk,
+ struct partition_desc *pd)
+{
+ struct partition_entry *table;
+ struct partition pentry;
+ uint8_t *buffer = buf;
+ int i;
+
+ table = (struct partition_entry *)&buffer[446];
+
+ /* valid for x86 BIOS based disks only */
+ if (IS_ENABLED(CONFIG_DISK_BIOS) && blk->num_blocks == 0)
+ blk->num_blocks = disk_guess_size(blk->dev, table);
+
+ for (i = 0; i < 4; i++) {
+ pentry.first_sec = get_unaligned_le32(&table[i].partition_start);
+ pentry.size = get_unaligned_le32(&table[i].partition_size);
+
+ if (pentry.first_sec != 0) {
+ pd->parts[pd->used_entries].first_sec = pentry.first_sec;
+ pd->parts[pd->used_entries].size = pentry.size;
+ pd->used_entries++;
+ } else {
+ dev_dbg(blk->dev, "Skipping empty partition %d\n", i);
+ }
+ }
+}
+
+struct partition_parser dos = {
+ .parse = dos_partition,
+ .type = filetype_mbr,
+};
+
+static int dos_partition_init(void)
+{
+ return partition_parser_register(&dos);
+}
+postconsole_initcall(dos_partition_init);
diff --git a/common/partitions/parser.h b/common/partitions/parser.h
new file mode 100644
index 0000000000..13506c00a0
--- /dev/null
+++ b/common/partitions/parser.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2013 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+ *
+ * Under GPLv2 only
+ */
+
+#ifndef __PARTITIONS_PARSER_H__
+#define __PARTITIONS_PARSER_H__
+
+#include <block.h>
+#include <filetype.h>
+#include <linux/list.h>
+
+#define MAX_PARTITION 8
+
+struct partition {
+ uint64_t first_sec;
+ uint64_t size;
+};
+
+struct partition_desc {
+ int used_entries;
+ struct partition parts[MAX_PARTITION];
+};
+
+struct partition_parser {
+ void (*parse)(void *buf, struct block_device *blk, struct partition_desc *pd);
+ enum filetype type;
+
+ struct list_head list;
+};
+
+int partition_parser_register(struct partition_parser *p);
+
+#endif /* __PARTITIONS_PARSER_H__ */