summaryrefslogtreecommitdiffstats
path: root/common/partitions
diff options
context:
space:
mode:
Diffstat (limited to 'common/partitions')
-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 597f9ba581..b9f31c3784 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 = {