summaryrefslogtreecommitdiffstats
path: root/common
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2013-06-02 12:35:47 +0200
committerSascha Hauer <s.hauer@pengutronix.de>2013-06-02 12:35:47 +0200
commit5e7f8558475ea96283fec772381a46a12402c802 (patch)
treec58836ad66a5415931b76c942e2bc9ee9deb4bb7 /common
parente08e2faa04b4272a969c1551d5b6e184adfa1ec2 (diff)
parentb27af5cdf36c099b2c4f29e9b71252cc8d66e223 (diff)
downloadbarebox-5e7f8558475ea96283fec772381a46a12402c802.tar.gz
barebox-5e7f8558475ea96283fec772381a46a12402c802.tar.xz
Merge branch 'for-next/block'
Diffstat (limited to 'common')
-rw-r--r--common/block.c38
-rw-r--r--common/partitions.c2
-rw-r--r--common/partitions/Kconfig1
-rw-r--r--common/partitions/dos.c88
-rw-r--r--common/partitions/efi.c4
5 files changed, 122 insertions, 11 deletions
diff --git a/common/block.c b/common/block.c
index 120d65928e..ad07f8b2e2 100644
--- a/common/block.c
+++ b/common/block.c
@@ -176,7 +176,7 @@ static void *block_get(struct block_device *blk, int block)
return outdata;
}
-static ssize_t block_read(struct cdev *cdev, void *buf, size_t count,
+static ssize_t block_op_read(struct cdev *cdev, void *buf, size_t count,
loff_t offset, unsigned long flags)
{
struct block_device *blk = cdev->priv;
@@ -253,7 +253,7 @@ static int block_put(struct block_device *blk, const void *buf, int block)
return 0;
}
-static ssize_t block_write(struct cdev *cdev, const void *buf, size_t count,
+static ssize_t block_op_write(struct cdev *cdev, const void *buf, size_t count,
loff_t offset, ulong flags)
{
struct block_device *blk = cdev->priv;
@@ -310,14 +310,14 @@ static ssize_t block_write(struct cdev *cdev, const void *buf, size_t count,
}
#endif
-static int block_close(struct cdev *cdev)
+static int block_op_close(struct cdev *cdev)
{
struct block_device *blk = cdev->priv;
return writebuffer_flush(blk);
}
-static int block_flush(struct cdev *cdev)
+static int block_op_flush(struct cdev *cdev)
{
struct block_device *blk = cdev->priv;
@@ -325,12 +325,12 @@ static int block_flush(struct cdev *cdev)
}
static struct file_operations block_ops = {
- .read = block_read,
+ .read = block_op_read,
#ifdef CONFIG_BLOCK_WRITE
- .write = block_write,
+ .write = block_op_write,
#endif
- .close = block_close,
- .flush = block_flush,
+ .close = block_op_close,
+ .flush = block_op_flush,
.lseek = dev_lseek_default,
};
@@ -387,3 +387,25 @@ int blockdevice_unregister(struct block_device *blk)
return 0;
}
+
+int block_read(struct block_device *blk, void *buf, int block, int num_blocks)
+{
+ int ret;
+
+ ret = cdev_read(&blk->cdev, buf,
+ num_blocks << blk->blockbits,
+ (loff_t)block << blk->blockbits, 0);
+
+ return ret < 0 ? ret : 0;
+}
+
+int block_write(struct block_device *blk, void *buf, int block, int num_blocks)
+{
+ int ret;
+
+ ret = cdev_write(&blk->cdev, buf,
+ num_blocks << blk->blockbits,
+ (loff_t)block << blk->blockbits, 0);
+
+ return ret < 0 ? ret : 0;
+}
diff --git a/common/partitions.c b/common/partitions.c
index 683b2586e4..35a604c35f 100644
--- a/common/partitions.c
+++ b/common/partitions.c
@@ -128,7 +128,7 @@ int parse_partition_table(struct block_device *blk)
pdesc = xzalloc(sizeof(*pdesc));
buf = dma_alloc(SECTOR_SIZE * 2);
- rc = blk->ops->read(blk, buf, 0, 2);
+ rc = block_read(blk, buf, 0, 2);
if (rc != 0) {
dev_err(blk->dev, "Cannot read MBR/partition table\n");
goto on_error;
diff --git a/common/partitions/Kconfig b/common/partitions/Kconfig
index 077091cde2..90238ad382 100644
--- a/common/partitions/Kconfig
+++ b/common/partitions/Kconfig
@@ -1,5 +1,6 @@
config PARTITION_DISK
depends on PARTITION
+ depends on BLOCK
bool "DISK partition support"
help
Add support for handling common partition tables on all kind of disk
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 = {
diff --git a/common/partitions/efi.c b/common/partitions/efi.c
index e450eebf77..ee1326e622 100644
--- a/common/partitions/efi.c
+++ b/common/partitions/efi.c
@@ -86,7 +86,7 @@ static gpt_entry *alloc_read_gpt_entries(struct block_device *blk,
from = le64_to_cpu(pgpt_head->partition_entry_lba);
size = count / GPT_BLOCK_SIZE;
- ret = blk->ops->read(blk, pte, from, size);
+ ret = block_read(blk, pte, from, size);
if (ret) {
kfree(pte);
pte=NULL;
@@ -121,7 +121,7 @@ static gpt_header *alloc_read_gpt_header(struct block_device *blk,
if (!gpt)
return NULL;
- ret = blk->ops->read(blk, gpt, lba, 1);
+ ret = block_read(blk, gpt, lba, 1);
if (ret) {
kfree(gpt);
gpt=NULL;