summaryrefslogtreecommitdiffstats
path: root/common/partitions/dos.c
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2013-04-04 12:01:22 +0200
committerSascha Hauer <s.hauer@pengutronix.de>2013-06-02 12:35:13 +0200
commitb27af5cdf36c099b2c4f29e9b71252cc8d66e223 (patch)
tree9e8d73eedf0054bf9998c61fd7b66dd79db09940 /common/partitions/dos.c
parent5014bf0cc55abd3d10ff71fb18187d479b8aeb21 (diff)
downloadbarebox-b27af5cdf36c099b2c4f29e9b71252cc8d66e223.tar.gz
partition: DOS: Add parameter for the NT disk Signature
The NT disk Signature is a unique 32-bit value in the MBR allowing to identify a MSDOS partitioned disk. The signature can be used to specify the Linux rootfs. This patch adds support for the NT disk Signature in the form of a device parameter which can both be read and written. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'common/partitions/dos.c')
-rw-r--r--common/partitions/dos.c88
1 files changed, 88 insertions, 0 deletions
diff --git a/common/partitions/dos.c b/common/partitions/dos.c
index 597f9ba..b9f31c3 100644
--- a/common/partitions/dos.c
+++ b/common/partitions/dos.c
@@ -16,6 +16,8 @@
#include <disks.h>
#include <init.h>
#include <asm/unaligned.h>
+#include <dma.h>
+#include <linux/err.h>
#include "parser.h"
@@ -40,6 +42,74 @@ static int disk_guess_size(struct device_d *dev, struct partition_entry *table)
return (int)size;
}
+static void *read_mbr(struct block_device *blk)
+{
+ void *buf = dma_alloc(SECTOR_SIZE);
+ int ret;
+
+ ret = block_read(blk, buf, 0, 1);
+ if (ret) {
+ free(buf);
+ return NULL;
+ }
+
+ return buf;
+}
+
+static int write_mbr(struct block_device *blk, void *buf)
+{
+ int ret;
+
+ ret = block_write(blk, buf, 0, 1);
+ if (ret)
+ return ret;
+
+ return block_flush(blk);
+}
+
+struct disk_signature_priv {
+ uint32_t signature;
+ struct block_device *blk;
+};
+
+static int dos_set_disk_signature(struct param_d *p, void *_priv)
+{
+ struct disk_signature_priv *priv = _priv;
+ struct block_device *blk = priv->blk;
+ void *buf;
+ __le32 *disksigp;
+ int ret;
+
+ buf = read_mbr(blk);
+ if (!buf)
+ return -EIO;
+
+ disksigp = buf + 0x1b8;
+
+ *disksigp = cpu_to_le32(priv->signature);
+
+ ret = write_mbr(blk, buf);
+
+ free(buf);
+
+ return ret;
+}
+
+static int dos_get_disk_signature(struct param_d *p, void *_priv)
+{
+ struct disk_signature_priv *priv = _priv;
+ struct block_device *blk = priv->blk;
+ void *buf;
+
+ buf = read_mbr(blk);
+ if (!buf)
+ return -EIO;
+
+ priv->signature = le32_to_cpup((__le32 *)(buf + 0x1b8));
+
+ return 0;
+}
+
/**
* Check if a DOS like partition describes this block device
* @param blk Block device to register to
@@ -55,6 +125,7 @@ static void dos_partition(void *buf, struct block_device *blk,
struct partition pentry;
uint8_t *buffer = buf;
int i;
+ struct disk_signature_priv *dsp;
table = (struct partition_entry *)&buffer[446];
@@ -74,6 +145,23 @@ static void dos_partition(void *buf, struct block_device *blk,
dev_dbg(blk->dev, "Skipping empty partition %d\n", i);
}
}
+
+ dsp = xzalloc(sizeof(*dsp));
+ dsp->blk = blk;
+
+ /*
+ * This parameter contains the NT disk signature. This allows to
+ * to specify the Linux rootfs using the following syntax:
+ *
+ * root=PARTUUID=ssssssss-pp
+ *
+ * where ssssssss is a zero-filled hex representation of the 32-bit
+ * signature and pp is a zero-filled hex representation of the 1-based
+ * partition number.
+ */
+ dev_add_param_int(blk->dev, "nt_signature",
+ dos_set_disk_signature, dos_get_disk_signature,
+ &dsp->signature, "%08x", dsp);
}
static struct partition_parser dos = {