Skip to contentSkip to conversation

Loop block device for sandbox

PATCH New Pavel Herrmann 4 participants 43 messages Aug 29, 2012 – Sep 28, 2012 Block layer

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 Loop block device for sandbox

This driver uses files as block devices, can be used for testing disk operations on sandbox. Port count and filenames are set in board config.

---
 drivers/block/Makefile    |   1 +
 drivers/block/loop.c      | 107 ++++++++++++++++++++++++++++++++++++++++++++++
 include/configs/sandbox.h |   9 ++++
 3 files changed, 117 insertions(+)
 create mode 100644 drivers/block/loop.c
drivers/block/Makefile +1 -0
index f1ebdcc..5eecf37 100644
@@ -40,6 +40,7 @@ COBJS-$(CONFIG_SATA_SIL) += sata_sil.o
 COBJS-$(CONFIG_IDE_SIL680) += sil680.o
 COBJS-$(CONFIG_SCSI_SYM53C8XX) += sym53c8xx.o
 COBJS-$(CONFIG_SYSTEMACE) += systemace.o
+COBJS-${CONFIG_SATA_LOOP} += loop.o
 
 COBJS	:= $(COBJS-y)
 SRCS	:= $(COBJS:.o=.c)
drivers/block/loop.c new file +107 -0

107 lines not on this page · raw message

include/configs/sandbox.h +9 -0
index 0220386..412341f 100644
@@ -93,4 +93,13 @@
 					"stdout=serial\0" \
 					"stderr=serial\0"
 
+/* SATA loopback device */
+#define CONFIG_CMD_SATA
+#define CONFIG_SATA_LOOP
+#define CONFIG_SATA_LOOP_DISKS {"disk1", "disk2"}
+#define CONFIG_SYS_SATA_MAX_DEVICE 2
+#define CONFIG_DOS_PARTITION
+#define CONFIG_CMD_FAT
+#define CONFIG_CMD_EXT2
+
 #endif
Signature · 1 line
1.7.12
#1 lore raw

PATCH 1/1 Loop block device for sandbox

More CC

Quoted 156 lines · On Wednesday 29 August 2012 17:46:43 Pavel Herrmann wrote:

This driver uses files as block devices, can be used for testing disk operations on sandbox. Port count and filenames are set in board config.

---
 drivers/block/Makefile    |   1 +
 drivers/block/loop.c      | 107
++++++++++++++++++++++++++++++++++++++++++++++ include/configs/sandbox.h | 
 9 ++++
 3 files changed, 117 insertions(+)
 create mode 100644 drivers/block/loop.c
drivers/block/Makefile +1 -0
index f1ebdcc..5eecf37 100644
@@ -40,6 +40,7 @@ COBJS-$(CONFIG_SATA_SIL) += sata_sil.o
 COBJS-$(CONFIG_IDE_SIL680) += sil680.o
 COBJS-$(CONFIG_SCSI_SYM53C8XX) += sym53c8xx.o
 COBJS-$(CONFIG_SYSTEMACE) += systemace.o
+COBJS-${CONFIG_SATA_LOOP} += loop.o
 
 COBJS	:= $(COBJS-y)
 SRCS	:= $(COBJS:.o=.c)
drivers/block/loop.c new file +107 -0
new file mode 100644
index 0000000..c9edfc3
@@ -0,0 +1,107 @@
+/*
+ * (C) Copyright 2012
+ * Pavel Herrmann <[email protected]>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <part.h>
+#include <ata.h>
+#include <libata.h>
+#include <errno.h>
+#include <os.h>
+
+static const char revision[] = "0.0";
+static const char vendor[] = "loopback";
+
+static const char * const filenames[] = CONFIG_SATA_LOOP_DISKS;
+static int max_devs = CONFIG_SYS_SATA_MAX_DEVICE;
+
+extern block_dev_desc_t sata_dev_desc[];
+
+int init_sata(int dev)
+{
+	block_dev_desc_t *pdev = &(sata_dev_desc[dev]);
+	int fd;
+
+	if ((dev < 0) || (dev >= max_devs)) {
+		printf("file index %d is out of range\n", dev);
+		return -EINVAL;
+	}
+
+	fd = os_open(filenames[dev], OS_O_RDWR);
+	/* this is ugly, but saves allocation for 1 int */
+	pdev->priv = (void *) (long) fd;
+
+	return 0;
+}
+
+lbaint_t sata_read(int dev, lbaint_t start, lbaint_t blkcnt, void *buffer)
+{
+	block_dev_desc_t *pdev = &(sata_dev_desc[dev]);
+	int fd = (long) pdev->priv;
+	lbaint_t retval;
+
+	os_lseek(fd, start*ATA_SECT_SIZE, OS_SEEK_SET);
+	retval = os_read(fd, buffer, ATA_SECT_SIZE * blkcnt);
+
+	return retval/ATA_SECT_SIZE;
+}
+
+lbaint_t sata_write(int dev, lbaint_t start, lbaint_t blkcnt, void *buffer)
+{
+	block_dev_desc_t *pdev = &(sata_dev_desc[dev]);
+	int fd = (long) pdev->priv;
+	lbaint_t retval;
+
+	os_lseek(fd, start*ATA_SECT_SIZE, OS_SEEK_SET);
+	retval = os_write(fd, buffer, ATA_SECT_SIZE * blkcnt);
+
+	return retval/ATA_SECT_SIZE;
+}
+
+int scan_sata(int dev)
+{
+	block_dev_desc_t *pdev = &(sata_dev_desc[dev]);
+	int fd = (long) pdev->priv;
+	int namelen;
+	lbaint_t bytes = 0;
+	memcpy(pdev->vendor, vendor, sizeof(vendor));
+	memcpy(pdev->revision, revision, sizeof(revision));
+	namelen = sizeof(filenames[dev]);
+	if (namelen > 20)
+		namelen = 20;
+	memcpy(pdev->product, filenames[dev], namelen);
+	pdev->product[20] = 0;
+
+	if (fd != -1) {
+		pdev->type = DEV_TYPE_HARDDISK;
+		pdev->blksz = ATA_SECT_SIZE;
+		pdev->lun = 0;
+
+		bytes = os_lseek(fd, 0, OS_SEEK_END);
+		pdev->lba = bytes/ATA_SECT_SIZE;
+	}
+
+	printf("SATA loop info:\nfilename: %s\nsize: %lu\nblock count: %lu\n",
+		filenames[dev], bytes, pdev->lba);
+
+	return 0;
+}
include/configs/sandbox.h +9 -0
index 0220386..412341f 100644
@@ -93,4 +93,13 @@
 					"stdout=serial\0" \
 					"stderr=serial\0"
 
+/* SATA loopback device */
+#define CONFIG_CMD_SATA
+#define CONFIG_SATA_LOOP
+#define CONFIG_SATA_LOOP_DISKS {"disk1", "disk2"}
+#define CONFIG_SYS_SATA_MAX_DEVICE 2
+#define CONFIG_DOS_PARTITION
+#define CONFIG_CMD_FAT
+#define CONFIG_CMD_EXT2
+
 #endif
#2 lore raw

PATCH 1/1 Loop block device for sandbox

In reply to Pavel Herrmann

Dear Pavel Herrmann,

Quoted 18 lines

This driver uses files as block devices, can be used for testing disk operations on sandbox. Port count and filenames are set in board config.

---
 drivers/block/Makefile    |   1 +
 drivers/block/loop.c      | 107
++++++++++++++++++++++++++++++++++++++++++++++ include/configs/sandbox.h |
  9 ++++
 3 files changed, 117 insertions(+)
 create mode 100644 drivers/block/loop.c
drivers/block/Makefile +0 -0
index f1ebdcc..5eecf37 100644

drivers/block/Makefile COBJS-$(CONFIG_SATA_SIL) += sata_sil.o · line 43

Quoted 4 lines
drivers/block/Makefile +1 -0
@@ -40,6 +40,7 @@ COBJS-$(CONFIG_SATA_SIL) += sata_sil.o
 COBJS-$(CONFIG_IDE_SIL680) += sil680.o
 COBJS-$(CONFIG_SCSI_SYM53C8XX) += sym53c8xx.o
 COBJS-$(CONFIG_SYSTEMACE) += systemace.o
+COBJS-${CONFIG_SATA_LOOP} += loop.o

Move this to a more descriptive filename, maybe sata_loopback.c ?

Quoted 40 lines
drivers/block/Makefile +0 -0
 COBJS	:= $(COBJS-y)
 SRCS	:= $(COBJS:.o=.c)
drivers/block/loop.c new file +31 -0
new file mode 100644
index 0000000..c9edfc3
@@ -0,0 +1,107 @@
+/*
+ * (C) Copyright 2012
+ * Pavel Herrmann <[email protected]>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <part.h>
+#include <ata.h>
+#include <libata.h>
+#include <errno.h>
+#include <os.h>
+
+static const char revision[] = "0.0";

drivers/block/loop.c line 41

Quoted 10 lines
drivers/block/loop.c new file +10 -0
+static const char vendor[] = "loopback";
+
+static const char * const filenames[] = CONFIG_SATA_LOOP_DISKS;
+static int max_devs = CONFIG_SYS_SATA_MAX_DEVICE;
+
+extern block_dev_desc_t sata_dev_desc[];
+
+int init_sata(int dev)
+{
+	block_dev_desc_t *pdev = &(sata_dev_desc[dev]);

Superfluous braces ... Actually, I think sata_dev_desc as it would work very well too.

drivers/block/loop.c line 45

Quoted 4 lines
drivers/block/loop.c new file +4 -0
+	int fd;
+
+	if ((dev < 0) || (dev >= max_devs)) {
+		printf("file index %d is out of range\n", dev);

Capital "F" and period at the end of a sentence.

drivers/block/loop.c line 50

Quoted 5 lines
drivers/block/loop.c new file +5 -0
+		return -EINVAL;
+	}
+
+	fd = os_open(filenames[dev], OS_O_RDWR);
+	/* this is ugly, but saves allocation for 1 int */

Same here.

drivers/block/loop.c line 59

Quoted 9 lines
drivers/block/loop.c new file +9 -0
+	pdev->priv = (void *) (long) fd;
+
+	return 0;
+}
+
+lbaint_t sata_read(int dev, lbaint_t start, lbaint_t blkcnt, void *buffer)
+{
+	block_dev_desc_t *pdev = &(sata_dev_desc[dev]);
+	int fd = (long) pdev->priv;

If pdev is NULL, this will crash

Quoted 10 lines
drivers/block/loop.c new file +9 -0
+	lbaint_t retval;
+
+	os_lseek(fd, start*ATA_SECT_SIZE, OS_SEEK_SET);
+	retval = os_read(fd, buffer, ATA_SECT_SIZE * blkcnt);
+
+	return retval/ATA_SECT_SIZE;
+}
+
+lbaint_t sata_write(int dev, lbaint_t start, lbaint_t blkcnt, void

*buffer) +{

drivers/block/loop.c line 62

Quoted 5 lines
drivers/block/loop.c new file +5 -0
+	block_dev_desc_t *pdev = &(sata_dev_desc[dev]);
+	int fd = (long) pdev->priv;
+	lbaint_t retval;
+
+	os_lseek(fd, start*ATA_SECT_SIZE, OS_SEEK_SET);

Please do the multiplication in a consistent manner, same for division etc. ... like you do on the following line (x1 [space] oper [space] x2).

Besides, lseek can fail, can it not?

drivers/block/loop.c line 85

Quoted 11 lines
drivers/block/loop.c new file +11 -0
+	retval = os_write(fd, buffer, ATA_SECT_SIZE * blkcnt);
+
+	return retval/ATA_SECT_SIZE;
+}
+
+int scan_sata(int dev)
+{
+	block_dev_desc_t *pdev = &(sata_dev_desc[dev]);
+	int fd = (long) pdev->priv;
+	int namelen;
+	lbaint_t bytes = 0;

newline here

drivers/block/loop.c line 88

Quoted 3 lines
drivers/block/loop.c new file +3 -0
+	memcpy(pdev->vendor, vendor, sizeof(vendor));
+	memcpy(pdev->revision, revision, sizeof(revision));
+	namelen = sizeof(filenames[dev]);

newline here

drivers/block/loop.c line 90

Quoted 2 lines
drivers/block/loop.c new file +2 -0
+	if (namelen > 20)
+		namelen = 20;

Why do you trim down the string, won't simple strdup() work?

newline here

drivers/block/loop.c line 94

Quoted 4 lines
drivers/block/loop.c new file +4 -0
+	memcpy(pdev->product, filenames[dev], namelen);
+	pdev->product[20] = 0;
+
+	if (fd != -1) {

And if "fd" is -1 ?

Quoted 19 lines
drivers/block/loop.c new file +13 -0
+		pdev->type = DEV_TYPE_HARDDISK;
+		pdev->blksz = ATA_SECT_SIZE;
+		pdev->lun = 0;
+
+		bytes = os_lseek(fd, 0, OS_SEEK_END);
+		pdev->lba = bytes/ATA_SECT_SIZE;
+	}
+
+	printf("SATA loop info:\nfilename: %s\nsize: %lu\nblock count: %lu\n",
+		filenames[dev], bytes, pdev->lba);
+
+	return 0;
+}
include/configs/sandbox.h +0 -0
index 0220386..412341f 100644
@@ -93,4 +93,13 @@
 					"stdout=serial\0" \

include/configs/sandbox.h line 103

Quoted 10 lines
include/configs/sandbox.h +8 -0
 					"stderr=serial\0"
 
+/* SATA loopback device */
+#define CONFIG_CMD_SATA
+#define CONFIG_SATA_LOOP
+#define CONFIG_SATA_LOOP_DISKS {"disk1", "disk2"}
+#define CONFIG_SYS_SATA_MAX_DEVICE 2
+#define CONFIG_DOS_PARTITION
+#define CONFIG_CMD_FAT
+#define CONFIG_CMD_EXT2

Move this to a separate patch.

include/configs/sandbox.h line 104

Quoted 1 line
include/configs/sandbox.h +0 -0
 #endif

Best regards,
Marek Vasut

#3 lore raw

PATCH 1/1 Loop block device for sandbox

On Thursday 30 of August 2012 00:18:18 Marek Vasut wrote:
...snip...

Quoted 8 lines

drivers/block/loop.c line 41

Quoted 5 lines
drivers/block/loop.c new file +5 -0
+extern block_dev_desc_t sata_dev_desc[];
+
+int init_sata(int dev)
+{
+	block_dev_desc_t *pdev = &(sata_dev_desc[dev]);

Superfluous braces ... Actually, I think sata_dev_desc as it would work very well too.

Straight copy from dwc_ahsata.c, makes it more readable thought, as the order of operation is not very intuitive IMHO.

Quoted 7 lines

drivers/block/loop.c line 59

Quoted 5 lines

+lbaint_t sata_read(int dev, lbaint_t start, lbaint_t blkcnt, void *buffer)

drivers/block/loop.c new file +3 -0
+{
+	block_dev_desc_t *pdev = &(sata_dev_desc[dev]);
+	int fd = (long) pdev->priv;

If pdev is NULL, this will crash

well, it isn't, at least not from the command - thats why you define the number of ports in advance, you get "dev" already range-checked

Quoted 9 lines
Quoted 9 lines
drivers/block/loop.c new file +9 -0
+	lbaint_t retval;
+
+	os_lseek(fd, start*ATA_SECT_SIZE, OS_SEEK_SET);
+	retval = os_read(fd, buffer, ATA_SECT_SIZE * blkcnt);
+
+	return retval/ATA_SECT_SIZE;
+}
+
+lbaint_t sata_write(int dev, lbaint_t start, lbaint_t blkcnt, void
Quoted 8 lines

drivers/block/loop.c line 62

Quoted 6 lines

*buffer) +{

drivers/block/loop.c new file +5 -0
+	block_dev_desc_t *pdev = &(sata_dev_desc[dev]);
+	int fd = (long) pdev->priv;
+	lbaint_t retval;
+
+	os_lseek(fd, start*ATA_SECT_SIZE, OS_SEEK_SET);

Besides, lseek can fail, can it not?

If you open a pipe (or nothing), yes
in the first case, you shouldn't, in the second, the I/O op will harmlessly fail as well

Quoted 4 lines

drivers/block/loop.c line 90

Quoted 2 lines
drivers/block/loop.c new file +2 -0
+	if (namelen > 20)
+		namelen = 20;

Why do you trim down the string, won't simple strdup() work?

nah, the destination is char[21], as it is the exact length of corresponding field in ATA identify response (one more for a 0 at the end)

Quoted 6 lines

drivers/block/loop.c line 94

Quoted 4 lines
drivers/block/loop.c new file +4 -0
+	memcpy(pdev->product, filenames[dev], namelen);
+	pdev->product[20] = 0;
+
+	if (fd != -1) {

And if "fd" is -1 ?

then all defaults to an invalid device, because you failed to open the file, for whatever the reason.

"agreed" to the other comments

Best Regards
Pavel Herrmann

#4 lore raw

PATCH 1/1 Loop block device for sandbox

Dear Pavel Herrmann,

Quoted 12 lines · On Thursday 30 of August 2012 00:18:18 Marek Vasut wrote:

...snip...

Quoted 8 lines

drivers/block/loop.c line 41

Quoted 5 lines
drivers/block/loop.c new file +5 -0
+extern block_dev_desc_t sata_dev_desc[];
+
+int init_sata(int dev)
+{
+	block_dev_desc_t *pdev = &(sata_dev_desc[dev]);

Superfluous braces ... Actually, I think sata_dev_desc as it would work very well too.

Quoted 2 lines

Straight copy from dwc_ahsata.c, makes it more readable thought, as the order of operation is not very intuitive IMHO.

sata_dev_desc + dev ?

Quoted 10 lines
Quoted 7 lines

drivers/block/loop.c line 59

Quoted 5 lines

+lbaint_t sata_read(int dev, lbaint_t start, lbaint_t blkcnt, void *buffer)

drivers/block/loop.c new file +3 -0
+{
+	block_dev_desc_t *pdev = &(sata_dev_desc[dev]);
+	int fd = (long) pdev->priv;

If pdev is NULL, this will crash

well, it isn't, at least not from the command - thats why you define the number of ports in advance, you get "dev" already range-checked

Range check is fine, but will pdev be inited? It's a pointer from some array.

Quoted 18 lines
Quoted 9 lines
Quoted 9 lines
drivers/block/loop.c new file +9 -0
+	lbaint_t retval;
+
+	os_lseek(fd, start*ATA_SECT_SIZE, OS_SEEK_SET);
+	retval = os_read(fd, buffer, ATA_SECT_SIZE * blkcnt);
+
+	return retval/ATA_SECT_SIZE;
+}
+
+lbaint_t sata_write(int dev, lbaint_t start, lbaint_t blkcnt, void
Quoted 8 lines

drivers/block/loop.c line 62

Quoted 6 lines

*buffer) +{

drivers/block/loop.c new file +5 -0
+	block_dev_desc_t *pdev = &(sata_dev_desc[dev]);
+	int fd = (long) pdev->priv;
+	lbaint_t retval;
+
+	os_lseek(fd, start*ATA_SECT_SIZE, OS_SEEK_SET);

Besides, lseek can fail, can it not?

Quoted 2 lines

If you open a pipe (or nothing), yes
in the first case, you shouldn't

Shouldn't ... what? Sorry, I cannot parse this.

Quoted 2 lines

in the second, the I/O op will harmlessly
fail as well

How so?

Quoted 7 lines
Quoted 4 lines

drivers/block/loop.c line 90

Quoted 2 lines
drivers/block/loop.c new file +2 -0
+	if (namelen > 20)
+		namelen = 20;

Why do you trim down the string, won't simple strdup() work?

nah, the destination is char[21], as it is the exact length of corresponding field in ATA identify response (one more for a 0 at the end)

I see, is it a full path ? If so, it might be a better idea to use the filename itself instead of the whole path. So you'd prevent names like "~/../foo/../.././bar.img" .

Quoted 9 lines
Quoted 6 lines

drivers/block/loop.c line 94

Quoted 4 lines
drivers/block/loop.c new file +4 -0
+	memcpy(pdev->product, filenames[dev], namelen);
+	pdev->product[20] = 0;
+
+	if (fd != -1) {

And if "fd" is -1 ?

then all defaults to an invalid device, because you failed to open the file, for whatever the reason.

At least the printf below will choke, since pdev->lba is uninited

Quoted 8 lines

"agreed" to the other comments

Best Regards
Pavel Herrmann
_______________________________________________
U-Boot mailing list
U-Boot at lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot

Best regards,
Marek Vasut

#5 lore raw

PATCH 1/1 Loop block device for sandbox

Quoted 14 lines · On Thursday 30 of August 2012 20:45:13 Marek Vasut wrote:

Dear Pavel Herrmann,

Quoted 12 lines · On Thursday 30 of August 2012 00:18:18 Marek Vasut wrote:

...snip...

Quoted 8 lines

drivers/block/loop.c line 41

Quoted 5 lines
drivers/block/loop.c new file +5 -0
+extern block_dev_desc_t sata_dev_desc[];
+
+int init_sata(int dev)
+{
+	block_dev_desc_t *pdev = &(sata_dev_desc[dev]);

Superfluous braces ... Actually, I think sata_dev_desc as it would work very well too.

Quoted 4 lines
Quoted 2 lines

Straight copy from dwc_ahsata.c, makes it more readable thought, as the order of operation is not very intuitive IMHO.

sata_dev_desc + dev ?

even less intuitive

Quoted 8 lines
Quoted 8 lines
Quoted 7 lines

drivers/block/loop.c line 59

Quoted 5 lines

+lbaint_t sata_read(int dev, lbaint_t start, lbaint_t blkcnt, void *buffer)

drivers/block/loop.c new file +3 -0
+{
+	block_dev_desc_t *pdev = &(sata_dev_desc[dev]);
+	int fd = (long) pdev->priv;

If pdev is NULL, this will crash

Quoted 5 lines
Quoted 2 lines

well, it isn't, at least not from the command - thats why you define the number of ports in advance, you get "dev" already range-checked

Range check is fine, but will pdev be inited? It's a pointer from some array.

init_sata is called first, so pdev is inited (see cmd_sata.c)

Quoted 18 lines
Quoted 18 lines
Quoted 17 lines
Quoted 10 lines
drivers/block/loop.c new file +9 -0
+	lbaint_t retval;
+
+	os_lseek(fd, start*ATA_SECT_SIZE, OS_SEEK_SET);
+	retval = os_read(fd, buffer, ATA_SECT_SIZE * blkcnt);
+
+	return retval/ATA_SECT_SIZE;
+}
+
+lbaint_t sata_write(int dev, lbaint_t start, lbaint_t blkcnt, void

*buffer) +{

drivers/block/loop.c line 62

Quoted 5 lines
drivers/block/loop.c new file +5 -0
+	block_dev_desc_t *pdev = &(sata_dev_desc[dev]);
+	int fd = (long) pdev->priv;
+	lbaint_t retval;
+
+	os_lseek(fd, start*ATA_SECT_SIZE, OS_SEEK_SET);

Besides, lseek can fail, can it not?

Quoted 4 lines
Quoted 2 lines

If you open a pipe (or nothing), yes
in the first case, you shouldn't

Shouldn't ... what? Sorry, I cannot parse this.

shouldn't do that - means i agree there should be a check in case you are actively trying to break things, and use pipes/sockets as loop blocks

Quoted 4 lines
Quoted 2 lines

in the second, the I/O op will harmlessly
fail as well

How so?

because then the fd is -1, and read/write will do the right thing there (nothing, return -1 and set errno to EBADF)

Quoted 11 lines
Quoted 7 lines
Quoted 4 lines

drivers/block/loop.c line 90

Quoted 2 lines
drivers/block/loop.c new file +2 -0
+	if (namelen > 20)
+		namelen = 20;

Why do you trim down the string, won't simple strdup() work?

nah, the destination is char[21], as it is the exact length of corresponding field in ATA identify response (one more for a 0 at the end)

I see, is it a full path ? If so, it might be a better idea to use the filename itself instead of the whole path. So you'd prevent names like "~/../foo/../.././bar.img" .

yes, i was thinking about "...${last 17 bytes of the name}" if the name was longer, but this proved significantly simpler for demonstrating the general idea.

Quoted 11 lines
Quoted 9 lines
Quoted 6 lines

drivers/block/loop.c line 94

Quoted 4 lines
drivers/block/loop.c new file +4 -0
+	memcpy(pdev->product, filenames[dev], namelen);
+	pdev->product[20] = 0;
+
+	if (fd != -1) {

And if "fd" is -1 ?

then all defaults to an invalid device, because you failed to open the file, for whatever the reason.

At least the printf below will choke, since pdev->lba is uninited

not the case. sata_dev_desc is inited in cmd_sata.c, and therefore by not doing anything we get an empty device

Best Regards
Pavel Herrmann

#6 lore raw

PATCH 1/1 Loop block device for sandbox

Dear Pavel Herrmann,

Quoted 15 lines · On Thursday 30 of August 2012 20:45:13 Marek Vasut wrote:
Quoted 14 lines

Dear Pavel Herrmann,

Quoted 12 lines · On Thursday 30 of August 2012 00:18:18 Marek Vasut wrote:

...snip...

Quoted 8 lines

drivers/block/loop.c line 41

Quoted 5 lines
drivers/block/loop.c new file +5 -0
+extern block_dev_desc_t sata_dev_desc[];
+
+int init_sata(int dev)
+{
+	block_dev_desc_t *pdev = &(sata_dev_desc[dev]);

Superfluous braces ... Actually, I think sata_dev_desc as it would work very well too.

Quoted 6 lines
Quoted 4 lines
Quoted 2 lines

Straight copy from dwc_ahsata.c, makes it more readable thought, as the order of operation is not very intuitive IMHO.

sata_dev_desc + dev ?

even less intuitive

Why so?

Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 7 lines

drivers/block/loop.c line 59

Quoted 5 lines

+lbaint_t sata_read(int dev, lbaint_t start, lbaint_t blkcnt, void *buffer)

drivers/block/loop.c new file +3 -0
+{
+	block_dev_desc_t *pdev = &(sata_dev_desc[dev]);
+	int fd = (long) pdev->priv;

If pdev is NULL, this will crash

Quoted 7 lines
Quoted 5 lines
Quoted 2 lines

well, it isn't, at least not from the command - thats why you define the number of ports in advance, you get "dev" already range-checked

Range check is fine, but will pdev be inited? It's a pointer from some array.

init_sata is called first, so pdev is inited (see cmd_sata.c)

Unless it fails. Then what ?

Quoted 18 lines
Quoted 18 lines
Quoted 18 lines
Quoted 17 lines
Quoted 10 lines
drivers/block/loop.c new file +9 -0
+	lbaint_t retval;
+
+	os_lseek(fd, start*ATA_SECT_SIZE, OS_SEEK_SET);
+	retval = os_read(fd, buffer, ATA_SECT_SIZE * blkcnt);
+
+	return retval/ATA_SECT_SIZE;
+}
+
+lbaint_t sata_write(int dev, lbaint_t start, lbaint_t blkcnt, void

*buffer) +{

drivers/block/loop.c line 62

Quoted 5 lines
drivers/block/loop.c new file +5 -0
+	block_dev_desc_t *pdev = &(sata_dev_desc[dev]);
+	int fd = (long) pdev->priv;
+	lbaint_t retval;
+
+	os_lseek(fd, start*ATA_SECT_SIZE, OS_SEEK_SET);

Besides, lseek can fail, can it not?

Quoted 7 lines
Quoted 4 lines
Quoted 2 lines

If you open a pipe (or nothing), yes
in the first case, you shouldn't

Shouldn't ... what? Sorry, I cannot parse this.

shouldn't do that - means i agree there should be a check in case you are actively trying to break things, and use pipes/sockets as loop blocks

Good

Quoted 7 lines
Quoted 4 lines
Quoted 2 lines

in the second, the I/O op will harmlessly
fail as well

How so?

because then the fd is -1, and read/write will do the right thing there (nothing, return -1 and set errno to EBADF)

From write(2)

-->8--

RETURN VALUE
On success, the number of bytes written is returned (zero indicates
nothing was written). On error, -1 is returned,
and errno is set appropriately.

If count is zero and fd refers to a regular file, then write() may return
a failure status if one of the errors below
is detected. If no errors are detected, 0 will be returned without
causing any other effect. If count is zero and fd
refers to a file other than a regular file, the results are not
specified.

--8<--

I don't see the case where fd = -1 handled there@all. The last sentence resembles it, but in that case, the behavior is undefined. Can you elaborate please?

Quoted 9 lines
Quoted 9 lines
Quoted 8 lines
Quoted 4 lines

drivers/block/loop.c line 90

Quoted 2 lines
drivers/block/loop.c new file +2 -0
+	if (namelen > 20)
+		namelen = 20;

Why do you trim down the string, won't simple strdup() work?

nah, the destination is char[21], as it is the exact length of corresponding field in ATA identify response (one more for a 0 at the end)

Quoted 7 lines
Quoted 3 lines

I see, is it a full path ? If so, it might be a better idea to use the filename itself instead of the whole path. So you'd prevent names like "~/../foo/../.././bar.img" .

yes, i was thinking about "...${last 17 bytes of the name}" if the name was longer, but this proved significantly simpler for demonstrating the general idea.

I think the FS code might contain some function to fixup the path and get filename from path.

Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
Quoted 6 lines

drivers/block/loop.c line 94

Quoted 4 lines
drivers/block/loop.c new file +4 -0
+	memcpy(pdev->product, filenames[dev], namelen);
+	pdev->product[20] = 0;
+
+	if (fd != -1) {

And if "fd" is -1 ?

Quoted 7 lines
Quoted 4 lines
Quoted 2 lines

then all defaults to an invalid device, because you failed to open the file, for whatever the reason.

At least the printf below will choke, since pdev->lba is uninited

not the case. sata_dev_desc is inited in cmd_sata.c, and therefore by not doing anything we get an empty device

I see ... shall we also move all these memcpy() calls in to if (fd != -1) then?

Quoted 2 lines

Best Regards
Pavel Herrmann

Best regards,
Marek Vasut

#7 lore raw

PATCH 1/1 Loop block device for sandbox

Quoted 21 lines · On Thursday 30 August 2012 23:53:58 Marek Vasut wrote:

Dear Pavel Herrmann,

Quoted 19 lines · On Thursday 30 of August 2012 20:45:13 Marek Vasut wrote:
Quoted 18 lines

Dear Pavel Herrmann,

Quoted 15 lines · On Thursday 30 of August 2012 00:18:18 Marek Vasut wrote:

...snip...

Quoted 8 lines

drivers/block/loop.c line 41

Quoted 5 lines
drivers/block/loop.c new file +5 -0
+extern block_dev_desc_t sata_dev_desc[];
+
+int init_sata(int dev)
+{
+	block_dev_desc_t *pdev = &(sata_dev_desc[dev]);

Superfluous braces ... Actually, I think sata_dev_desc as it would work very well too.

Straight copy from dwc_ahsata.c, makes it more readable thought, as the
order of operation is not very intuitive IMHO.

Quoted 5 lines
Quoted 3 lines
Quoted 1 line

sata_dev_desc + dev ?

even less intuitive

Why so?

because of the silent "*sizeof(sata_dev_desc)".
I know this is standardized in C (so is the order of operands), but doing "+" on non-numbers is a little too C++ for me. I know that generated code will be eactly the same in all cases.

Quoted 11 lines
Quoted 11 lines
Quoted 11 lines
Quoted 10 lines
Quoted 7 lines

drivers/block/loop.c line 59

Quoted 5 lines

+lbaint_t sata_read(int dev, lbaint_t start, lbaint_t blkcnt, void *buffer)

drivers/block/loop.c new file +3 -0
+{
+	block_dev_desc_t *pdev = &(sata_dev_desc[dev]);
+	int fd = (long) pdev->priv;

If pdev is NULL, this will crash

well, it isn't, at least not from the command - thats why you define the number of ports in advance, you get "dev" already range-checked

Quoted 6 lines
Quoted 4 lines
Quoted 2 lines

Range check is fine, but will pdev be inited? It's a pointer from some array.

init_sata is called first, so pdev is inited (see cmd_sata.c)

Unless it fails. Then what ?

the only way init can "fail" is if it gets a wrong device number (which should not happen), or if it cannot open the file, in which case it still sets pdev as -1.

Quoted 24 lines
Quoted 7 lines
Quoted 4 lines
Quoted 2 lines

in the second, the I/O op will harmlessly
fail as well

How so?

because then the fd is -1, and read/write will do the right thing there (nothing, return -1 and set errno to EBADF)

From write(2)

-->8--

RETURN VALUE
On success, the number of bytes written is returned (zero indicates
nothing was written). On error, -1 is returned,
and errno is set appropriately.

If count is zero and fd refers to a regular file, then write() may
return a failure status if one of the errors below
is detected. If no errors are detected, 0 will be returned without
causing any other effect. If count is zero and fd
refers to a file other than a regular file, the results are not
specified.

Quoted 5 lines

--8<--

I don't see the case where fd = -1 handled there at all. The last sentence resembles it, but in that case, the behavior is undefined. Can you elaborate please?

RETURN VALUE
...
On error, -1 is returned, and errno is set appropriately.
...
ERRORS
...
EBADF fd is not a valid file descriptor or is not open for writing.
...
-1 is definitely not a valid file descriptor.
this point is moot, as checking success of lseek (because of pipes/sockets) will filter out invalid fd as well

Quoted 13 lines
Quoted 13 lines
Quoted 12 lines
Quoted 8 lines
Quoted 4 lines

drivers/block/loop.c line 90

Quoted 2 lines
drivers/block/loop.c new file +2 -0
+	if (namelen > 20)
+		namelen = 20;

Why do you trim down the string, won't simple strdup() work?

nah, the destination is char[21], as it is the exact length of corresponding field in ATA identify response (one more for a 0 at the end)

I see, is it a full path ? If so, it might be a better idea to use the filename itself instead of the whole path. So you'd prevent names like "~/../foo/../.././bar.img" .

Quoted 8 lines
Quoted 5 lines

yes, i was thinking about "...${last 17 bytes of the name}" if the name was
longer, but this proved significantly simpler for demonstrating the general
idea.

I think the FS code might contain some function to fixup the path and get filename from path.

that still wouldn't solve the problem, flename can still be over 20 bytes long

Quoted 10 lines
Quoted 10 lines
Quoted 10 lines
Quoted 9 lines
Quoted 6 lines

drivers/block/loop.c line 94

Quoted 4 lines
drivers/block/loop.c new file +4 -0
+	memcpy(pdev->product, filenames[dev], namelen);
+	pdev->product[20] = 0;
+
+	if (fd != -1) {

And if "fd" is -1 ?

then all defaults to an invalid device, because you failed to open the file, for whatever the reason.

Quoted 7 lines
Quoted 4 lines
Quoted 1 line

At least the printf below will choke, since pdev->lba is uninited

not the case. sata_dev_desc is inited in cmd_sata.c, and therefore by not doing anything we get an empty device

I see ... shall we also move all these memcpy() calls in to if (fd != -1) then?

I'd like to know that the device is a loopback, and what filename, not just that it failed to init

Pavel Herrmann

#8 lore raw

PATCH 1/1 Loop block device for sandbox

Dear Pavel Herrmann,

Quoted 24 lines · On Thursday 30 August 2012 23:53:58 Marek Vasut wrote:
Quoted 23 lines

Dear Pavel Herrmann,

Quoted 21 lines · On Thursday 30 of August 2012 20:45:13 Marek Vasut wrote:
Quoted 19 lines

Dear Pavel Herrmann,

Quoted 12 lines · On Thursday 30 of August 2012 00:18:18 Marek Vasut wrote:

...snip...

Quoted 8 lines

Review

Quoted 5 lines
(quoted diff) +5 -0
+extern block_dev_desc_t sata_dev_desc[];
+
+int init_sata(int dev)
+{
+	block_dev_desc_t *pdev = &(sata_dev_desc[dev]);

Superfluous braces ... Actually, I think sata_dev_desc as it would work very well too.

Quoted 3 lines

Straight copy from dwc_ahsata.c, makes it more readable thought, as the
order of operation is not very intuitive IMHO.

sata_dev_desc + dev ?

Quoted 8 lines
Quoted 3 lines
Quoted 1 line

even less intuitive

Why so?

because of the silent "*sizeof(sata_dev_desc)".
I know this is standardized in C (so is the order of operands), but doing "+" on non-numbers is a little too C++ for me. I know that generated code will be eactly the same in all cases.

It's simple increment of a pointer, normal thing.

Quoted 15 lines
Quoted 15 lines
Quoted 15 lines
Quoted 14 lines
Quoted 11 lines
Quoted 7 lines

Review

Quoted 5 lines

+lbaint_t sata_read(int dev, lbaint_t start, lbaint_t blkcnt, void *buffer)

(quoted diff) +3 -0
+{
+	block_dev_desc_t *pdev = &(sata_dev_desc[dev]);
+	int fd = (long) pdev->priv;

If pdev is NULL, this will crash

well, it isn't, at least not from the command - thats why you define the number of ports in advance, you get "dev" already range-checked

Range check is fine, but will pdev be inited? It's a pointer from some array.

Quoted 7 lines
Quoted 3 lines
Quoted 1 line

init_sata is called first, so pdev is inited (see cmd_sata.c)

Unless it fails. Then what ?

the only way init can "fail" is if it gets a wrong device number (which should not happen), or if it cannot open the file, in which case it still sets pdev as -1.

If pdev is -1, then this explodes for certain, on unaligned access and on wrong ptr deref.

Quoted 40 lines
Quoted 32 lines
Quoted 7 lines
Quoted 4 lines
Quoted 2 lines

in the second, the I/O op will harmlessly
fail as well

How so?

because then the fd is -1, and read/write will do the right thing there (nothing, return -1 and set errno to EBADF)

From write(2)

-->8--

RETURN VALUE

On success, the number of bytes written is returned (zero indicates

nothing was written). On error, -1 is returned,

and errno is set appropriately.

If count is zero and fd refers to a regular file, then write() may

return a failure status if one of the errors below

is detected. If no errors are detected, 0 will be returned without

causing any other effect. If count is zero and fd

refers to a file other than a regular file, the results are not

Quoted 7 lines

specified.

--8<--

I don't see the case where fd = -1 handled there at all. The last sentence resembles it, but in that case, the behavior is undefined. Can you elaborate please?

Quoted 9 lines

RETURN VALUE
...
On error, -1 is returned, and errno is set appropriately.
...
ERRORS
...
EBADF fd is not a valid file descriptor or is not open for writing.
...
-1 is definitely not a valid file descriptor.

I see, good catch.

Quoted 22 lines

this point is moot, as checking success of lseek (because of pipes/sockets) will filter out invalid fd as well

Quoted 19 lines
Quoted 18 lines
Quoted 5 lines
Quoted 5 lines
Quoted 4 lines

Review

Quoted 2 lines
(quoted diff) +2 -0
+	if (namelen > 20)
+		namelen = 20;

Why do you trim down the string, won't simple strdup() work?

Quoted 7 lines
Quoted 3 lines

nah, the destination is char[21], as it is the exact length of corresponding field in ATA identify response (one more for a 0 at the end)

I see, is it a full path ? If so, it might be a better idea to use the filename itself instead of the whole path. So you'd prevent names like "~/../foo/../.././bar.img" .

yes, i was thinking about "...${last 17 bytes of the name}" if the name was
longer, but this proved significantly simpler for demonstrating the general
idea.

Quoted 5 lines
Quoted 2 lines

I think the FS code might contain some function to fixup the path and get filename from path.

that still wouldn't solve the problem, flename can still be over 20 bytes long

Then pick the first 20 ... but this is really discutable

Quoted 12 lines
Quoted 12 lines
Quoted 12 lines
Quoted 11 lines
Quoted 9 lines
Quoted 6 lines

Review

Quoted 4 lines
(quoted diff) +4 -0
+	memcpy(pdev->product, filenames[dev], namelen);
+	pdev->product[20] = 0;
+
+	if (fd != -1) {

And if "fd" is -1 ?

then all defaults to an invalid device, because you failed to open the file, for whatever the reason.

At least the printf below will choke, since pdev->lba is uninited

Quoted 8 lines
Quoted 5 lines
Quoted 2 lines

not the case. sata_dev_desc is inited in cmd_sata.c, and therefore by not doing anything we get an empty device

I see ... shall we also move all these memcpy() calls in to if (fd != -1) then?

I'd like to know that the device is a loopback, and what filename, not just that it failed to init

But are such data used somewhere further down the road?

Quoted 1 line

Pavel Herrmann

Best regards,
Marek Vasut

#9 lore raw

PATCH 1/1 Loop block device for sandbox

Quoted 17 lines · On Friday 31 of August 2012 14:57:41 Marek Vasut wrote:
Quoted 17 lines
Quoted 17 lines
Quoted 16 lines
Quoted 8 lines
Quoted 8 lines
Quoted 7 lines

Review

Quoted 5 lines

+lbaint_t sata_read(int dev, lbaint_t start, lbaint_t blkcnt, void *buffer)

(quoted diff) +3 -0
+{
+	block_dev_desc_t *pdev = &(sata_dev_desc[dev]);
+	int fd = (long) pdev->priv;

If pdev is NULL, this will crash

Quoted 6 lines
Quoted 3 lines

well, it isn't, at least not from the command - thats why you define the number of ports in advance, you get "dev" already range-checked

Range check is fine, but will pdev be inited? It's a pointer from some array.

init_sata is called first, so pdev is inited (see cmd_sata.c)

Quoted 8 lines
Quoted 5 lines
Quoted 1 line

Unless it fails. Then what ?

the only way init can "fail" is if it gets a wrong device number (which should not happen), or if it cannot open the file, in which case it still sets pdev as -1.

If pdev is -1, then this explodes for certain, on unaligned access and on wrong ptr deref.

again, no

there is no pointer in this, pdev->priv is actually an int stored as void*, pdev itself is pointer to a global array.
which one does explode in your case?

Quoted 19 lines
Quoted 19 lines
Quoted 18 lines
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
Quoted 6 lines

Review

Quoted 4 lines
(quoted diff) +4 -0
+	memcpy(pdev->product, filenames[dev], namelen);
+	pdev->product[20] = 0;
+
+	if (fd != -1) {

And if "fd" is -1 ?

Quoted 7 lines
Quoted 4 lines
Quoted 2 lines

then all defaults to an invalid device, because you failed to open the file, for whatever the reason.

At least the printf below will choke, since pdev->lba is uninited

not the case. sata_dev_desc is inited in cmd_sata.c, and therefore by not doing anything we get an empty device

I see ... shall we also move all these memcpy() calls in to if (fd != -1)
then?

Quoted 5 lines
Quoted 3 lines

I'd like to know that the device is a loopback, and what filename, not just
that it failed to init

But are such data used somewhere further down the road?

yes, "sata info" for example

Pavel Herrmann

#10 lore raw

PATCH 1/1 Loop block device for sandbox

Dear Pavel Herrmann,

Quoted 24 lines · On Friday 31 of August 2012 14:57:41 Marek Vasut wrote:
Quoted 23 lines
Quoted 22 lines
Quoted 12 lines
Quoted 12 lines
Quoted 12 lines
Quoted 11 lines
Quoted 7 lines

Review

Quoted 5 lines

+lbaint_t sata_read(int dev, lbaint_t start, lbaint_t blkcnt, void *buffer)

(quoted diff) +3 -0
+{
+	block_dev_desc_t *pdev = &(sata_dev_desc[dev]);
+	int fd = (long) pdev->priv;

If pdev is NULL, this will crash

well, it isn't, at least not from the command - thats why you define the number of ports in advance, you get "dev" already range-checked

Quoted 6 lines
Quoted 4 lines
Quoted 2 lines

Range check is fine, but will pdev be inited? It's a pointer from some array.

init_sata is called first, so pdev is inited (see cmd_sata.c)

Unless it fails. Then what ?

the only way init can "fail" is if it gets a wrong device number (which should not happen), or if it cannot open the file, in which case it still sets pdev as -1.

Quoted 8 lines
Quoted 2 lines

If pdev is -1, then this explodes for certain, on unaligned access and on wrong ptr deref.

again, no

there is no pointer in this, pdev->priv is actually an int stored as void*, pdev itself is pointer to a global array.
which one does explode in your case?

pdev, but given that the pointer is inited, I see the issue at hand now.

Quoted 19 lines
Quoted 19 lines
Quoted 19 lines
Quoted 18 lines
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
Quoted 6 lines

Review

Quoted 4 lines
(quoted diff) +4 -0
+	memcpy(pdev->product, filenames[dev], namelen);
+	pdev->product[20] = 0;
+
+	if (fd != -1) {

And if "fd" is -1 ?

Quoted 7 lines
Quoted 4 lines
Quoted 2 lines

then all defaults to an invalid device, because you failed to open the file, for whatever the reason.

At least the printf below will choke, since pdev->lba is uninited

not the case. sata_dev_desc is inited in cmd_sata.c, and therefore by not doing anything we get an empty device

I see ... shall we also move all these memcpy() calls in to if (fd != -1)
then?

Quoted 7 lines
Quoted 5 lines
Quoted 3 lines

I'd like to know that the device is a loopback, and what filename, not just
that it failed to init

But are such data used somewhere further down the road?

yes, "sata info" for example

And how does it determine that the init failed?

I think we're almost clear on these things.

Quoted 1 line

Pavel Herrmann

Best regards,
Marek Vasut

#11 lore raw

PATCH 1/1 Loop block device for sandbox

Quoted 25 lines · On Friday 31 of August 2012 18:02:22 Marek Vasut wrote:
Quoted 25 lines
Quoted 25 lines
Quoted 24 lines
Quoted 13 lines
Quoted 13 lines
Quoted 12 lines
Quoted 9 lines
Quoted 6 lines

Review

Quoted 4 lines
(quoted diff) +4 -0
+	memcpy(pdev->product, filenames[dev], namelen);
+	pdev->product[20] = 0;
+
+	if (fd != -1) {

And if "fd" is -1 ?

then all defaults to an invalid device, because you failed to open the file, for whatever the reason.

At least the printf below will choke, since pdev->lba is uninited

Quoted 7 lines
Quoted 2 lines

not the case. sata_dev_desc is inited in cmd_sata.c, and therefore by not doing anything we get an empty device

I see ... shall we also move all these memcpy() calls in to if (fd !=
-1)
then?

I'd like to know that the device is a loopback, and what filename, not just
that it failed to init

Quoted 5 lines
Quoted 3 lines
Quoted 1 line

But are such data used somewhere further down the road?

yes, "sata info" for example

And how does it determine that the init failed?

given that the only thing the init does is open a file and put the decriptor to ->priv, you can tell whether it failed by looking at the descriptor (-1 means failed). the other fail-path in init is if it is given a wrong index, but that should never happen (at least not when called from cmd_sata)

on a disk with 0 size you cant have a partition table, so any FS code will refuse to work, any direct operation will fail because fd is -1

or did you mean a different "it"?

Quoted 1 line

I think we're almost clear on these things.

thats a relief

Pavel Herrmann

#12 lore raw

PATCH 1/1 Loop block device for sandbox

Dear Pavel Herrmann,

Quoted 38 lines · On Friday 31 of August 2012 18:02:22 Marek Vasut wrote:
Quoted 25 lines
Quoted 25 lines
Quoted 25 lines
Quoted 24 lines
Quoted 13 lines
Quoted 13 lines
Quoted 12 lines
Quoted 9 lines
Quoted 6 lines

Review

Quoted 4 lines
(quoted diff) +4 -0
+	memcpy(pdev->product, filenames[dev], namelen);
+	pdev->product[20] = 0;
+
+	if (fd != -1) {

And if "fd" is -1 ?

then all defaults to an invalid device, because you failed to open the file, for whatever the reason.

At least the printf below will choke, since pdev->lba is uninited

Quoted 7 lines
Quoted 2 lines

not the case. sata_dev_desc is inited in cmd_sata.c, and therefore by not doing anything we get an empty device

I see ... shall we also move all these memcpy() calls in to if (fd !=
-1)
then?

I'd like to know that the device is a loopback, and what filename, not just
that it failed to init

Quoted 5 lines
Quoted 3 lines
Quoted 1 line

But are such data used somewhere further down the road?

yes, "sata info" for example

And how does it determine that the init failed?

given that the only thing the init does is open a file and put the decriptor to ->priv, you can tell whether it failed by looking at the descriptor (-1 means failed). the other fail-path in init is if it is given a wrong index, but that should never happen (at least not when called from cmd_sata)

Quoted 4 lines

on a disk with 0 size you cant have a partition table, so any FS code will refuse to work, any direct operation will fail because fd is -1

or did you mean a different "it"?

Ok, I'd like to get it reviewed by someone else and then I think it can be applied.

Mike?

Quoted 5 lines
Quoted 1 line

I think we're almost clear on these things.

thats a relief

Pavel Herrmann

Best regards,
Marek Vasut

#13 lore raw

PATCH v2 1/2 Loop block device for sandbox

In reply to Pavel Herrmann

This driver uses files as block devices, can be used for testing disk operations on sandbox. Port count and filenames are set in board config.

---
Changes for v2:
split sandbox config off into separate patch (2/2) rename file to signify exported API
style fixes
show end of long filenames rather than beginning check for lseek errors to indicate non-regular file

 drivers/block/Makefile        |   1 +
 drivers/block/sata_loopback.c | 122 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 123 insertions(+)
 create mode 100644 drivers/block/sata_loopback.c
drivers/block/Makefile +1 -0
index f1ebdcc..c95651a 100644
@@ -40,6 +40,7 @@ COBJS-$(CONFIG_SATA_SIL) += sata_sil.o
 COBJS-$(CONFIG_IDE_SIL680) += sil680.o
 COBJS-$(CONFIG_SCSI_SYM53C8XX) += sym53c8xx.o
 COBJS-$(CONFIG_SYSTEMACE) += systemace.o
+COBJS-${CONFIG_SATA_LOOP} += sata_loopback.o
 
 COBJS	:= $(COBJS-y)
 SRCS	:= $(COBJS:.o=.c)
drivers/block/sata_loopback.c new file +122 -0

122 lines not on this page · raw message

Signature · 1 line
1.7.12
#14 lore raw

PATCH 2/2 Use loop block device in sandbox board

---
 include/configs/sandbox.h | 9 +++++++++
 1 file changed, 9 insertions(+)
include/configs/sandbox.h +9 -0
index 0220386..3126542 100644
@@ -93,4 +93,13 @@
 					"stdout=serial\0" \
 					"stderr=serial\0"
 
+/* SATA loopback device */
+#define CONFIG_CMD_SATA
+#define CONFIG_SATA_LOOP
+#define CONFIG_SATA_LOOP_DISKS {"disk1", "obscenelylongfilename", "disk3"}
+#define CONFIG_SYS_SATA_MAX_DEVICE 3
+#define CONFIG_DOS_PARTITION
+#define CONFIG_CMD_FAT
+#define CONFIG_CMD_EXT2
+
 #endif
Signature · 1 line
1.7.12
#15 lore raw

PATCH 2/2 Use loop block device in sandbox board

Dear Pavel Herrmann,

I don't understand what this patch does from the lacking description. Please add proper description to the patch. ALWAYS!

Quoted 13 lines
---
 include/configs/sandbox.h | 9 +++++++++
 1 file changed, 9 insertions(+)
include/configs/sandbox.h +0 -0
index 0220386..3126542 100644
@@ -93,4 +93,13 @@
 					"stdout=serial\0" \
 					"stderr=serial\0"
 

include/configs/sandbox.h line 105

Quoted 10 lines
include/configs/sandbox.h +9 -0
+/* SATA loopback device */
+#define CONFIG_CMD_SATA
+#define CONFIG_SATA_LOOP
+#define CONFIG_SATA_LOOP_DISKS {"disk1", "obscenelylongfilename", "disk3"}
+#define CONFIG_SYS_SATA_MAX_DEVICE 3
+#define CONFIG_DOS_PARTITION
+#define CONFIG_CMD_FAT
+#define CONFIG_CMD_EXT2
+
 #endif

Best regards,
Marek Vasut

#16 lore raw

PATCH 2/2 Use loop block device in sandbox board

Hi

Quoted 4 lines · On Saturday 01 of September 2012 16:20:12 Marek Vasut wrote:

Dear Pavel Herrmann,

I don't understand what this patch does from the lacking description. Please add proper description to the patch. ALWAYS!

see $title perhaps? there is not much more to say.

v2 on the way

Pavel Herrmann

#17 lore raw

PATCH v2 2/2 Use loop block device in sandbox board

In reply to Pavel Herrmann

Enable SATA_LOOP and a few disk-related commands for sandbox

---
changes for v2:
add a few words of description

 include/configs/sandbox.h | 9 +++++++++
 1 file changed, 9 insertions(+)
include/configs/sandbox.h +9 -0
index 0220386..3126542 100644
@@ -93,4 +93,13 @@
 					"stdout=serial\0" \
 					"stderr=serial\0"
 
+/* SATA loopback device */
+#define CONFIG_CMD_SATA
+#define CONFIG_SATA_LOOP
+#define CONFIG_SATA_LOOP_DISKS {"disk1", "obscenelylongfilename", "disk3"}
+#define CONFIG_SYS_SATA_MAX_DEVICE 3
+#define CONFIG_DOS_PARTITION
+#define CONFIG_CMD_FAT
+#define CONFIG_CMD_EXT2
+
 #endif
Signature · 1 line
1.7.12
#18 lore raw

PATCH v2 1/2 Loop block device for sandbox

In reply to Pavel Herrmann

Dear Pavel Herrmann,

Quoted 62 lines

This driver uses files as block devices, can be used for testing disk operations on sandbox. Port count and filenames are set in board config.

---
Changes for v2:
split sandbox config off into separate patch (2/2) rename file to signify exported API
style fixes
show end of long filenames rather than beginning check for lseek errors to indicate non-regular file

 drivers/block/Makefile        |   1 +
 drivers/block/sata_loopback.c | 122
++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 123
insertions(+)
 create mode 100644 drivers/block/sata_loopback.c
drivers/block/Makefile +1 -0
index f1ebdcc..c95651a 100644
@@ -40,6 +40,7 @@ COBJS-$(CONFIG_SATA_SIL) += sata_sil.o
 COBJS-$(CONFIG_IDE_SIL680) += sil680.o
 COBJS-$(CONFIG_SCSI_SYM53C8XX) += sym53c8xx.o
 COBJS-$(CONFIG_SYSTEMACE) += systemace.o
+COBJS-${CONFIG_SATA_LOOP} += sata_loopback.o
 
 COBJS	:= $(COBJS-y)
 SRCS	:= $(COBJS:.o=.c)
drivers/block/sata_loopback.c new file +25 -0
new file mode 100644
index 0000000..7f25a4f
@@ -0,0 +1,122 @@
+/*
+ * (C) Copyright 2012
+ * Pavel Herrmann <[email protected]>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <part.h>

drivers/block/sata_loopback.c line 35

Quoted 10 lines
drivers/block/sata_loopback.c new file +10 -0
+#include <ata.h>
+#include <libata.h>
+#include <errno.h>
+#include <os.h>
+
+static const char revision[] = "0.0";
+static const char vendor[] = "SATA loopback";
+
+static const char * const filenames[] = CONFIG_SATA_LOOP_DISKS;
+static int max_devs = CONFIG_SYS_SATA_MAX_DEVICE;

One more thing is missing -- documentation for these (add to doc/ ). Alternatively (which would be much better), let sandbox uboot accept params and supply these as params.

Quoted 76 lines
drivers/block/sata_loopback.c new file +36 -0
+extern block_dev_desc_t sata_dev_desc[];
+
+int init_sata(int dev)
+{
+	block_dev_desc_t *pdev = &sata_dev_desc[dev];
+	int fd;
+
+	if ((dev < 0) || (dev >= max_devs)) {
+		printf("File index %d is out of range.\n", dev);
+		return -EINVAL;
+	}
+
+	fd = os_open(filenames[dev], OS_O_RDWR);
+	/* This is ugly, but saves allocation for 1 int. */
+	pdev->priv = (void *) (long) fd;
+
+	return 0;
+}
+
+lbaint_t sata_read(int dev, lbaint_t start, lbaint_t blkcnt, void *buffer)
+{
+	block_dev_desc_t *pdev = &sata_dev_desc[dev];
+	int fd = (long) pdev->priv;
+	lbaint_t start_byte = ATA_SECT_SIZE * start;
+	lbaint_t length_byte = ATA_SECT_SIZE * blkcnt;
+	lbaint_t retval;
+
+	if ( os_lseek(fd, start_byte, OS_SEEK_SET) != start_byte)
+		return -1;
+
+	retval = os_read(fd, buffer, length_byte);
+
+	return retval/ATA_SECT_SIZE;
+}
+
+lbaint_t sata_write(int dev, lbaint_t start, lbaint_t blkcnt, void

*buffer) +{

drivers/block/sata_loopback.c new file +39 -0
+	block_dev_desc_t *pdev = &sata_dev_desc[dev];
+	int fd = (long) pdev->priv;
+	lbaint_t start_byte = ATA_SECT_SIZE * start;
+	lbaint_t length_byte = ATA_SECT_SIZE * blkcnt;
+	lbaint_t retval;
+
+	if ( os_lseek(fd, start_byte, OS_SEEK_SET) != start_byte)
+		return -1;
+
+	retval = os_write(fd, buffer, length_byte);
+
+	return retval/ATA_SECT_SIZE;
+}
+
+int scan_sata(int dev)
+{
+	block_dev_desc_t *pdev = &sata_dev_desc[dev];
+	int fd = (long) pdev->priv;
+	int namelen;
+	const char *filename = filenames[dev];
+	lbaint_t bytes = 0;
+
+	memcpy(pdev->vendor, vendor, sizeof(vendor));
+	memcpy(pdev->revision, revision, sizeof(revision));
+	namelen = strlen(filenames[dev]);
+
+	if (namelen > 20) {
+		/* take the last 17 chars, prepend them with "..." */
+		filename += (namelen - 17);
+		memcpy(pdev->product, "...", 3);
+		memcpy(pdev->product+3, filename, 17);
+	} else
+		memcpy(pdev->product, filename, namelen);
+
+	pdev->product[20] = 0;
+
+	bytes = os_lseek(fd, 0, OS_SEEK_END);
+	if (bytes != -1) {
+		pdev->type = DEV_TYPE_HARDDISK;

drivers/block/sata_loopback.c line 122

Quoted 10 lines
drivers/block/sata_loopback.c new file +10 -0
+		pdev->blksz = ATA_SECT_SIZE;
+		pdev->lun = 0;
+		pdev->lba = bytes/ATA_SECT_SIZE;
+	}
+
+	printf("SATA loop info:\nfilename: %s\nsize: %lu\nblock count: %lu\n",
+		filenames[dev], bytes, pdev->lba);
+
+	return 0;
+}

Best regards,
Marek Vasut

#19 lore raw

PATCH v2 1/2 Loop block device for sandbox

Quoted 8 lines · On Monday 03 of September 2012 18:49:00 Marek Vasut wrote:

drivers/block/sata_loopback.c line 35

Quoted 6 lines
drivers/block/sata_loopback.c new file +6 -0
+
+static const char revision[] = "0.0";
+static const char vendor[] = "SATA loopback";
+
+static const char * const filenames[] = CONFIG_SATA_LOOP_DISKS;
+static int max_devs = CONFIG_SYS_SATA_MAX_DEVICE;

One more thing is missing -- documentation for these (add to doc/ ).

which file shoud that be exactly? README.sata has nothing about configs, i cannot find any README.sandbox or README.configs

Quoted 2 lines

Alternatively (which would be much better), let sandbox uboot accept params and supply these as params.

or even make a command that would allow you to specify a filename in runtime, possibly with a dynamic number of ports.

Pavel Herrmann

#20 lore raw

PATCH v2 1/2 Loop block device for sandbox

Dear Pavel Herrmann,

Quoted 10 lines · On Monday 03 of September 2012 18:49:00 Marek Vasut wrote:
Quoted 8 lines

drivers/block/sata_loopback.c line 35

Quoted 6 lines
drivers/block/sata_loopback.c new file +6 -0
+
+static const char revision[] = "0.0";
+static const char vendor[] = "SATA loopback";
+
+static const char * const filenames[] = CONFIG_SATA_LOOP_DISKS;
+static int max_devs = CONFIG_SYS_SATA_MAX_DEVICE;

One more thing is missing -- documentation for these (add to doc/ ).

Quoted 2 lines

which file shoud that be exactly? README.sata has nothing about configs, i cannot find any README.sandbox or README.configs

Create one ... especially for the newly added feature -- eg. README.sata_loopback or something,

Quoted 5 lines
Quoted 2 lines

Alternatively (which would be much better), let sandbox uboot accept params and supply these as params.

or even make a command that would allow you to specify a filename in runtime, possibly with a dynamic number of ports.

Good idea, indeed.

Quoted 1 line

Pavel Herrmann

Best regards,
Marek Vasut

#21 lore raw

PATCH v3 1/2 Loop block device for sandbox

In reply to Pavel Herrmann

This driver uses files as block devices, can be used for testing disk operations on sandbox.
A new command "sata_loop" is introduced to load files in runtime.

CC Marek Vasut <[email protected]>
CC Mike Frysinger <[email protected]>

---
Changes for v3:
introduce sata_loop command

Changes for v2:
split sandbox config off into separate patch (2/2) rename file to signify exported API
style fixes
show end of long filenames rather than beginning check for lseek errors to indicate non-regular file

 drivers/block/Makefile        |   1 +
 drivers/block/sata_loopback.c | 200 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 201 insertions(+)
 create mode 100644 drivers/block/sata_loopback.c
drivers/block/Makefile +1 -0
index f1ebdcc..c95651a 100644
@@ -40,6 +40,7 @@ COBJS-$(CONFIG_SATA_SIL) += sata_sil.o
 COBJS-$(CONFIG_IDE_SIL680) += sil680.o
 COBJS-$(CONFIG_SCSI_SYM53C8XX) += sym53c8xx.o
 COBJS-$(CONFIG_SYSTEMACE) += systemace.o
+COBJS-${CONFIG_SATA_LOOP} += sata_loopback.o
 
 COBJS	:= $(COBJS-y)
 SRCS	:= $(COBJS:.o=.c)
drivers/block/sata_loopback.c new file +200 -0

200 lines not on this page · raw message

Signature · 1 line
1.7.12
#22 lore raw

PATCH v3 2/2 Use loop block device in sandbox board

Enable SATA_LOOP and a few disk-related commands for sandbox

---
Changes for v3:
drop static names for loop devices

Changes for v2:
add a few words of description

 include/configs/sandbox.h | 8 ++++++++
 1 file changed, 8 insertions(+)
include/configs/sandbox.h +8 -0
index 0220386..c238feb 100644
@@ -93,4 +93,12 @@
 					"stdout=serial\0" \
 					"stderr=serial\0"
 
+/* SATA loopback device */
+#define CONFIG_CMD_SATA
+#define CONFIG_SATA_LOOP
+#define CONFIG_SYS_SATA_MAX_DEVICE 3
+#define CONFIG_DOS_PARTITION
+#define CONFIG_CMD_FAT
+#define CONFIG_CMD_EXT2
+
 #endif
Signature · 1 line
1.7.12
#23 lore raw

PATCH v3 1/2 Loop block device for sandbox

In reply to Pavel Herrmann

Dear Pavel Herrmann,

Quoted 7 lines

This driver uses files as block devices, can be used for testing disk operations on sandbox.
A new command "sata_loop" is introduced to load files in runtime.

CC Marek Vasut <[email protected]>
CC Mike Frysinger <[email protected]>

ERROR: "foo * bar" should be "foo *bar"
#136: FILE: drivers/block/sata_loopback.c:36:
+static char * filenames[CONFIG_SYS_SATA_MAX_DEVICE];

WARNING: externs should be avoided in .c files
#138: FILE: drivers/block/sata_loopback.c:38:
+extern block_dev_desc_t sata_dev_desc[];

ERROR: do not initialise statics to 0 or NULL
#142: FILE: drivers/block/sata_loopback.c:42:
+ static int zeroed = 0;

ERROR: spaces required around that '=' (ctx:VxV)
#150: FILE: drivers/block/sata_loopback.c:50:

+                       filenames[i]=strdup("");
                                    ^

ERROR: space prohibited after that open parenthesis '(' #181: FILE: drivers/block/sata_loopback.c:81:
+ if ( os_lseek(fd, start_byte, OS_SEEK_SET) != start_byte)

ERROR: space prohibited after that open parenthesis '(' #197: FILE: drivers/block/sata_loopback.c:97:
+ if ( os_lseek(fd, start_byte, OS_SEEK_SET) != start_byte)

ERROR: do not initialise statics to 0 or NULL
#256: FILE: drivers/block/sata_loopback.c:156:
+ static int zeroed = 0;

total: 6 errors, 1 warnings, 207 lines checked

Checkpatch and I never sleep, don't even try ;-)

Quoted 67 lines

---
Changes for v3:
introduce sata_loop command

Changes for v2:
split sandbox config off into separate patch (2/2) rename file to signify exported API
style fixes
show end of long filenames rather than beginning check for lseek errors to indicate non-regular file

 drivers/block/Makefile        |   1 +
 drivers/block/sata_loopback.c | 200
++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 201
insertions(+)
 create mode 100644 drivers/block/sata_loopback.c
drivers/block/Makefile +1 -0
index f1ebdcc..c95651a 100644
@@ -40,6 +40,7 @@ COBJS-$(CONFIG_SATA_SIL) += sata_sil.o
 COBJS-$(CONFIG_IDE_SIL680) += sil680.o
 COBJS-$(CONFIG_SCSI_SYM53C8XX) += sym53c8xx.o
 COBJS-$(CONFIG_SYSTEMACE) += systemace.o
+COBJS-${CONFIG_SATA_LOOP} += sata_loopback.o
 
 COBJS	:= $(COBJS-y)
 SRCS	:= $(COBJS:.o=.c)
drivers/block/sata_loopback.c new file +32 -0
new file mode 100644
index 0000000..0e6923b
@@ -0,0 +1,200 @@
+/*
+ * (C) Copyright 2012
+ * Pavel Herrmann <[email protected]>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <part.h>
+#include <ata.h>
+#include <libata.h>
+#include <errno.h>
+#include <os.h>
+#include <command.h>
+#include <malloc.h>
+

drivers/block/sata_loopback.c line 42

Quoted 10 lines
drivers/block/sata_loopback.c new file +10 -0
+static const char revision[] = "0.0";
+static const char vendor[] = "SATA loopback";
+
+static char * filenames[CONFIG_SYS_SATA_MAX_DEVICE];
+
+extern block_dev_desc_t sata_dev_desc[];
+
+int init_sata(int dev)
+{
+	static int zeroed = 0;

Is this really needed here and below? Pull this crap out.

drivers/block/sata_loopback.c line 46

Quoted 4 lines
drivers/block/sata_loopback.c new file +4 -0
+	block_dev_desc_t *pdev = &sata_dev_desc[dev];
+	int fd, old_fd;
+
+

Redundant newline

Quoted 9 lines
drivers/block/sata_loopback.c new file +9 -0
+	if (!zeroed) {
+		int i;
+		for (i = 0; i < CONFIG_SYS_SATA_MAX_DEVICE; i++)
+			filenames[i]=strdup("");
+		zeroed = 1;
+	}
+
+	if ((dev < 0) || (dev >= CONFIG_SYS_SATA_MAX_DEVICE)) {
+		printf("File index %d is out of range.\n", dev);

drivers/block/sata_loopback.c line 65

Quoted 10 lines
drivers/block/sata_loopback.c new file +10 -0
+		return -EINVAL;
+	}
+
+	fd = os_open(filenames[dev], OS_O_RDWR);
+	/* This is ugly, but saves allocation for 1 int. */
+	old_fd = (long) pdev->priv;
+	pdev->priv = (void *) (long) fd;
+	/*
+	 * sadly we cannot set -1 to all as above, because "sata init" will zero
+	 * this value before calling sata_init.

Sorry, I can't parse this.

Quoted 27 lines
drivers/block/sata_loopback.c new file +24 -0
+	 */
+	if ((old_fd > 2) || (old_fd < 0))
+		os_close(old_fd);
+
+	return 0;
+}
+
+lbaint_t sata_read(int dev, lbaint_t start, lbaint_t blkcnt, void *buffer)
+{
+	block_dev_desc_t *pdev = &sata_dev_desc[dev];
+	int fd = (long) pdev->priv;
+	lbaint_t start_byte = ATA_SECT_SIZE * start;
+	lbaint_t length_byte = ATA_SECT_SIZE * blkcnt;
+	lbaint_t retval;
+
+	if ( os_lseek(fd, start_byte, OS_SEEK_SET) != start_byte)
+		return -1;
+
+	retval = os_read(fd, buffer, length_byte);
+
+	return retval/ATA_SECT_SIZE;
+}
+
+lbaint_t sata_write(int dev, lbaint_t start, lbaint_t blkcnt, void

*buffer) +{

drivers/block/sata_loopback.c new file +2 -0
+	block_dev_desc_t *pdev = &sata_dev_desc[dev];
+	int fd = (long) pdev->priv;

drivers/block/sata_loopback.c line 102

Quoted 10 lines
drivers/block/sata_loopback.c new file +10 -0
+	lbaint_t start_byte = ATA_SECT_SIZE * start;
+	lbaint_t length_byte = ATA_SECT_SIZE * blkcnt;
+	lbaint_t retval;
+
+	if ( os_lseek(fd, start_byte, OS_SEEK_SET) != start_byte)
+		return -1;
+
+	retval = os_write(fd, buffer, length_byte);
+
+	return retval/ATA_SECT_SIZE;

a[space]operator[space]b ... did you ignore all my previous comments?

Quoted 44 lines
drivers/block/sata_loopback.c new file +44 -0
+}
+
+int scan_sata(int dev)
+{
+	block_dev_desc_t *pdev = &sata_dev_desc[dev];
+	int fd = (long) pdev->priv;
+	int namelen;
+	const char *filename = filenames[dev];
+	lbaint_t bytes = 0;
+
+	if ((dev < 0) || (dev >= CONFIG_SYS_SATA_MAX_DEVICE)) {
+		printf("File index %d is out of range.\n", dev);
+		return -EINVAL;
+	}
+
+	memcpy(pdev->vendor, vendor, sizeof(vendor));
+	memcpy(pdev->revision, revision, sizeof(revision));
+	namelen = strlen(filenames[dev]);
+
+	if (namelen > 20) {
+		/* take the last 17 chars, prepend them with "..." */
+		filename += (namelen - 17);
+		memcpy(pdev->product, "...", 3);
+		memcpy(pdev->product+3, filename, 17);
+	} else
+		memcpy(pdev->product, filename, namelen);
+
+	pdev->product[20] = 0;
+
+	bytes = os_lseek(fd, 0, OS_SEEK_END);
+	if (bytes != -1) {
+		pdev->type = DEV_TYPE_HARDDISK;
+		pdev->blksz = ATA_SECT_SIZE;
+		pdev->lun = 0;
+		pdev->lba = bytes/ATA_SECT_SIZE;
+		printf("SATA loop %d:\nfilename: %s\nsize: %lu\nblock count:"
+			" %lu\n", dev, filenames[dev], bytes, pdev->lba);
+	} else {
+		pdev->type = DEV_TYPE_HARDDISK;
+		pdev->blksz = ATA_SECT_SIZE;
+		pdev->lun = 0;
+		pdev->lba = 0;
+		printf("SATA loop %d:\nfilename: %s\nFAILED TO OPEN\n",
+			 dev, filenames[dev]);

drivers/block/sata_loopback.c line 156

Quoted 10 lines
drivers/block/sata_loopback.c new file +10 -0
+	}
+
+	return 0;
+}
+
+
+int do_loop(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	int dev = 0;
+	static int zeroed = 0;

move this out.

besides, I think it'd be much systematic to just scream at user to call "sata rescan" and bail out instead of doing it for him.

drivers/block/sata_loopback.c line 169

Quoted 12 lines
drivers/block/sata_loopback.c new file +12 -0
+	/* make sure we have valid filenames */
+	if (!zeroed) {
+		init_sata(0);
+		zeroed = 1;
+	}
+
+	switch (argc) {
+	case 0:
+	case 1:
+		return CMD_RET_USAGE;
+	case 2:
+		dev = simple_strtoul(argv[1], NULL, 10);

Ok, so if I run this command and ask for device 0xb00bf33d ... will this survive? Hint: it won't, rangecheck missing.

drivers/block/sata_loopback.c line 174

Quoted 5 lines
drivers/block/sata_loopback.c new file +5 -0
+		return scan_sata(dev);
+
+	case 3:
+		if (!strncmp(argv[1], "inf", 3)) {
+			dev = simple_strtoul(argv[2], NULL, 10);

Same here

drivers/block/sata_loopback.c line 181

Quoted 7 lines
drivers/block/sata_loopback.c new file +7 -0
+			return scan_sata(dev);
+		}
+		return CMD_RET_USAGE;
+	case 4:
+		if (!strncmp(argv[1], "load", 4)) {
+			dev = simple_strtoul(argv[2], NULL, 10);
+			if ((dev < 0) || (dev >= CONFIG_SYS_SATA_MAX_DEVICE)) {

And here you have it ?

Uh oh, I see, sata_scan() does it for you ... I'd say, abstract it out into lightweight static inline function.

Quoted 7 lines
drivers/block/sata_loopback.c new file +7 -0
+				printf("File index %d is out of range.\n", dev);
+				return -EINVAL;
+			}
+			free(filenames[dev]);
+			filenames[dev] = strdup(argv[3]);
+			init_sata(dev);
+			return scan_sata(dev);

drivers/block/sata_loopback.c line 198

Quoted 10 lines
drivers/block/sata_loopback.c new file +10 -0
+		}
+		return CMD_RET_USAGE;
+	}
+	return CMD_RET_USAGE;
+}
+
+U_BOOT_CMD(
+	sata_loop, 4, 1, do_loop,
+	"SATA loopback",
+	"[info] devnum - show info about loop devnum\n"

Make this "info" part mandatory. Than you can cut the whole argc loop into simple "if argc != 2 ; then fail" . And do simple checking for the first letter of the argument being either i or d .

drivers/block/sata_loopback.c line 199

Quoted 1 line
drivers/block/sata_loopback.c new file +1 -0
+	"sata_loop load devnum file - load file from host FS into loop devnum"

sata_loop is redundant above.

Quoted 1 line

+);

#24 lore raw

PATCH v3 1/2 Loop block device for sandbox

Quoted 35 lines · On Wednesday 05 September 2012 13:33:13 Marek Vasut wrote:

Dear Pavel Herrmann,

Quoted 7 lines

This driver uses files as block devices, can be used for testing disk operations on sandbox.
A new command "sata_loop" is introduced to load files in runtime.

CC Marek Vasut <[email protected]>
CC Mike Frysinger <[email protected]>

ERROR: "foo * bar" should be "foo *bar"
#136: FILE: drivers/block/sata_loopback.c:36:
+static char * filenames[CONFIG_SYS_SATA_MAX_DEVICE];

WARNING: externs should be avoided in .c files
#138: FILE: drivers/block/sata_loopback.c:38:
+extern block_dev_desc_t sata_dev_desc[];

ERROR: do not initialise statics to 0 or NULL
#142: FILE: drivers/block/sata_loopback.c:42:
+ static int zeroed = 0;

ERROR: spaces required around that '=' (ctx:VxV)
#150: FILE: drivers/block/sata_loopback.c:50:

+                       filenames[i]=strdup("");
                                    ^

ERROR: space prohibited after that open parenthesis '(' #181: FILE: drivers/block/sata_loopback.c:81:
+ if ( os_lseek(fd, start_byte, OS_SEEK_SET) != start_byte)

ERROR: space prohibited after that open parenthesis '(' #197: FILE: drivers/block/sata_loopback.c:97:
+ if ( os_lseek(fd, start_byte, OS_SEEK_SET) != start_byte)

Quoted 8 lines

ERROR: do not initialise statics to 0 or NULL
#256: FILE: drivers/block/sata_loopback.c:156:
+ static int zeroed = 0;

total: 6 errors, 1 warnings, 207 lines checked

Checkpatch and I never sleep, don't even try ;-)

sorry, my bad, i thought i had it on pre-commit

Quoted 77 lines
Quoted 77 lines

---

Changes for v3:
introduce sata_loop command

Changes for v2:
split sandbox config off into separate patch (2/2) rename file to signify exported API
style fixes
show end of long filenames rather than beginning check for lseek errors to indicate non-regular file

 drivers/block/Makefile        |   1 +
 drivers/block/sata_loopback.c | 200

++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 201 insertions(+)

 create mode 100644 drivers/block/sata_loopback.c
drivers/block/Makefile +1 -0
index f1ebdcc..c95651a 100644
@@ -40,6 +40,7 @@ COBJS-$(CONFIG_SATA_SIL) += sata_sil.o
 
 COBJS-$(CONFIG_IDE_SIL680) += sil680.o
 COBJS-$(CONFIG_SCSI_SYM53C8XX) += sym53c8xx.o
 COBJS-$(CONFIG_SYSTEMACE) += systemace.o
 
+COBJS-${CONFIG_SATA_LOOP} += sata_loopback.o
 

COBJS := $(COBJS-y)
SRCS := $(COBJS:.o=.c)

drivers/block/sata_loopback.c new file +36 -0
new file mode 100644
index 0000000..0e6923b
@@ -0,0 +1,200 @@
+/*
+ * (C) Copyright 2012
+ * Pavel Herrmann <[email protected]>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <part.h>
+#include <ata.h>
+#include <libata.h>
+#include <errno.h>
+#include <os.h>
+#include <command.h>
+#include <malloc.h>
+
+static const char revision[] = "0.0";
+static const char vendor[] = "SATA loopback";
+
+static char * filenames[CONFIG_SYS_SATA_MAX_DEVICE];
Quoted 8 lines

drivers/block/sata_loopback.c line 42

Quoted 6 lines
drivers/block/sata_loopback.c new file +6 -0
+
+extern block_dev_desc_t sata_dev_desc[];
+
+int init_sata(int dev)
+{
+	static int zeroed = 0;

Is this really needed here and below? Pull this crap out.

yes, because you dont know whetehr this gets called first from sata_loop or from "sata init"

Quoted 17 lines

drivers/block/sata_loopback.c line 46

Quoted 4 lines
drivers/block/sata_loopback.c new file +4 -0
+	block_dev_desc_t *pdev = &sata_dev_desc[dev];
+	int fd, old_fd;
+
+

Redundant newline

Quoted 10 lines
drivers/block/sata_loopback.c new file +10 -0
+	if (!zeroed) {
+		int i;
+		for (i = 0; i < CONFIG_SYS_SATA_MAX_DEVICE; i++)
+			filenames[i]=strdup("");
+		zeroed = 1;
+	}
+
+	if ((dev < 0) || (dev >= CONFIG_SYS_SATA_MAX_DEVICE)) {
+		printf("File index %d is out of range.\n", dev);
+		return -EINVAL;
Quoted 8 lines

drivers/block/sata_loopback.c

Quoted 8 lines
drivers/block/sata_loopback.c new file +8 -0
+	}
+
+	fd = os_open(filenames[dev], OS_O_RDWR);
+	/* This is ugly, but saves allocation for 1 int. */
+	old_fd = (long) pdev->priv;
+	pdev->priv = (void *) (long) fd;
+	/*
+	 * sadly we cannot set -1 to all as above, because "sata init" will 

zero

Quoted 102 lines

drivers/block/sata_loopback.c line 65

Quoted 1 line
drivers/block/sata_loopback.c new file +1 -0
+	 * this value before calling sata_init.

Sorry, I can't parse this.

Quoted 28 lines
drivers/block/sata_loopback.c new file +8 -0
+	 */
+	if ((old_fd > 2) || (old_fd < 0))
+		os_close(old_fd);
+
+	return 0;
+}
+
+lbaint_t sata_read(int dev, lbaint_t start, lbaint_t blkcnt, void

*buffer)

drivers/block/sata_loopback.c new file +16 -0
+{
+	block_dev_desc_t *pdev = &sata_dev_desc[dev];
+	int fd = (long) pdev->priv;
+	lbaint_t start_byte = ATA_SECT_SIZE * start;
+	lbaint_t length_byte = ATA_SECT_SIZE * blkcnt;
+	lbaint_t retval;
+
+	if ( os_lseek(fd, start_byte, OS_SEEK_SET) != start_byte)
+		return -1;
+
+	retval = os_read(fd, buffer, length_byte);
+
+	return retval/ATA_SECT_SIZE;
+}
+
+lbaint_t sata_write(int dev, lbaint_t start, lbaint_t blkcnt, void

*buffer) +{

drivers/block/sata_loopback.c new file +2 -0
+	block_dev_desc_t *pdev = &sata_dev_desc[dev];
+	int fd = (long) pdev->priv;

drivers/block/sata_loopback.c line 102

Quoted 10 lines
drivers/block/sata_loopback.c new file +10 -0
+	lbaint_t start_byte = ATA_SECT_SIZE * start;
+	lbaint_t length_byte = ATA_SECT_SIZE * blkcnt;
+	lbaint_t retval;
+
+	if ( os_lseek(fd, start_byte, OS_SEEK_SET) != start_byte)
+		return -1;
+
+	retval = os_write(fd, buffer, length_byte);
+
+	return retval/ATA_SECT_SIZE;

a[space]operator[space]b ... did you ignore all my previous comments?

Quoted 44 lines
drivers/block/sata_loopback.c new file +44 -0
+}
+
+int scan_sata(int dev)
+{
+	block_dev_desc_t *pdev = &sata_dev_desc[dev];
+	int fd = (long) pdev->priv;
+	int namelen;
+	const char *filename = filenames[dev];
+	lbaint_t bytes = 0;
+
+	if ((dev < 0) || (dev >= CONFIG_SYS_SATA_MAX_DEVICE)) {
+		printf("File index %d is out of range.\n", dev);
+		return -EINVAL;
+	}
+
+	memcpy(pdev->vendor, vendor, sizeof(vendor));
+	memcpy(pdev->revision, revision, sizeof(revision));
+	namelen = strlen(filenames[dev]);
+
+	if (namelen > 20) {
+		/* take the last 17 chars, prepend them with "..." */
+		filename += (namelen - 17);
+		memcpy(pdev->product, "...", 3);
+		memcpy(pdev->product+3, filename, 17);
+	} else
+		memcpy(pdev->product, filename, namelen);
+
+	pdev->product[20] = 0;
+
+	bytes = os_lseek(fd, 0, OS_SEEK_END);
+	if (bytes != -1) {
+		pdev->type = DEV_TYPE_HARDDISK;
+		pdev->blksz = ATA_SECT_SIZE;
+		pdev->lun = 0;
+		pdev->lba = bytes/ATA_SECT_SIZE;
+		printf("SATA loop %d:\nfilename: %s\nsize: %lu\nblock count:"
+			" %lu\n", dev, filenames[dev], bytes, pdev->lba);
+	} else {
+		pdev->type = DEV_TYPE_HARDDISK;
+		pdev->blksz = ATA_SECT_SIZE;
+		pdev->lun = 0;
+		pdev->lba = 0;
+		printf("SATA loop %d:\nfilename: %s\nFAILED TO OPEN\n",
+			 dev, filenames[dev]);

drivers/block/sata_loopback.c line 156

Quoted 10 lines
drivers/block/sata_loopback.c new file +10 -0
+	}
+
+	return 0;
+}
+
+
+int do_loop(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	int dev = 0;
+	static int zeroed = 0;

move this out.

Quoted 2 lines

besides, I think it'd be much systematic to just scream at user to call "sata rescan" and bail out instead of doing it for him.

i dont actually need a sata rescan, i just need to make sure i have dynamically allocated names, so i can safely call free() later, otherwise this segfaults when called before sata scan

Quoted 64 lines

drivers/block/sata_loopback.c line 169

Quoted 12 lines
drivers/block/sata_loopback.c new file +12 -0
+	/* make sure we have valid filenames */
+	if (!zeroed) {
+		init_sata(0);
+		zeroed = 1;
+	}
+
+	switch (argc) {
+	case 0:
+	case 1:
+		return CMD_RET_USAGE;
+	case 2:
+		dev = simple_strtoul(argv[1], NULL, 10);

Ok, so if I run this command and ask for device 0xb00bf33d ... will this survive? Hint: it won't, rangecheck missing.

drivers/block/sata_loopback.c line 174

Quoted 5 lines
drivers/block/sata_loopback.c new file +5 -0
+		return scan_sata(dev);
+
+	case 3:
+		if (!strncmp(argv[1], "inf", 3)) {
+			dev = simple_strtoul(argv[2], NULL, 10);

Same here

drivers/block/sata_loopback.c line 181

Quoted 7 lines
drivers/block/sata_loopback.c new file +7 -0
+			return scan_sata(dev);
+		}
+		return CMD_RET_USAGE;
+	case 4:
+		if (!strncmp(argv[1], "load", 4)) {
+			dev = simple_strtoul(argv[2], NULL, 10);
+			if ((dev < 0) || (dev >= CONFIG_SYS_SATA_MAX_DEVICE)) {

And here you have it ?

Uh oh, I see, sata_scan() does it for you ... I'd say, abstract it out into lightweight static inline function.

Quoted 7 lines
drivers/block/sata_loopback.c new file +7 -0
+				printf("File index %d is out of range.\n", dev);
+				return -EINVAL;
+			}
+			free(filenames[dev]);
+			filenames[dev] = strdup(argv[3]);
+			init_sata(dev);
+			return scan_sata(dev);

drivers/block/sata_loopback.c line 198

Quoted 10 lines
drivers/block/sata_loopback.c new file +10 -0
+		}
+		return CMD_RET_USAGE;
+	}
+	return CMD_RET_USAGE;
+}
+
+U_BOOT_CMD(
+	sata_loop, 4, 1, do_loop,
+	"SATA loopback",
+	"[info] devnum - show info about loop devnum\n"

Make this "info" part mandatory. Than you can cut the whole argc loop into simple "if argc != 2 ; then fail" . And do simple checking for the first letter of the argument being either i or d .

drivers/block/sata_loopback.c line 199

Quoted 1 line
drivers/block/sata_loopback.c new file +1 -0
+	"sata_loop load devnum file - load file from host FS into loop devnum"

sata_loop is redundant above.

Quoted 1 line

+);

#25 lore raw

PATCH v3 1/2 Loop block device for sandbox

Dear Pavel Herrmann,

[...]

Quoted 5 lines
Quoted 2 lines

besides, I think it'd be much systematic to just scream at user to call "sata rescan" and bail out instead of doing it for him.

i dont actually need a sata rescan, i just need to make sure i have dynamically allocated names

Sorry, I can't parse this ... but ...

Quoted 2 lines

, so i can safely call free() later, otherwise
this segfaults when called before sata scan

The free() function frees the memory space pointed to by ptr, which must have been returned by a previous call to malloc(), calloc() or realloc(). Otherwise, or if free(ptr) has already been called before, undefined behavior occurs. If ptr is NULL, no operation is performed.

So if you call free() on null pointer, nothing happens. Where's the real problem?

Quoted 65 lines
Quoted 65 lines

drivers/block/sata_loopback.c line 169

Quoted 12 lines
drivers/block/sata_loopback.c new file +12 -0
+	/* make sure we have valid filenames */
+	if (!zeroed) {
+		init_sata(0);
+		zeroed = 1;
+	}
+
+	switch (argc) {
+	case 0:
+	case 1:
+		return CMD_RET_USAGE;
+	case 2:
+		dev = simple_strtoul(argv[1], NULL, 10);

Ok, so if I run this command and ask for device 0xb00bf33d ... will this survive? Hint: it won't, rangecheck missing.

drivers/block/sata_loopback.c line 174

Quoted 5 lines
drivers/block/sata_loopback.c new file +5 -0
+		return scan_sata(dev);
+
+	case 3:
+		if (!strncmp(argv[1], "inf", 3)) {
+			dev = simple_strtoul(argv[2], NULL, 10);

Same here

drivers/block/sata_loopback.c line 181

Quoted 7 lines
drivers/block/sata_loopback.c new file +7 -0
+			return scan_sata(dev);
+		}
+		return CMD_RET_USAGE;
+	case 4:
+		if (!strncmp(argv[1], "load", 4)) {
+			dev = simple_strtoul(argv[2], NULL, 10);
+			if ((dev < 0) || (dev >= CONFIG_SYS_SATA_MAX_DEVICE)) {

And here you have it ?

Uh oh, I see, sata_scan() does it for you ... I'd say, abstract it out into lightweight static inline function.

Quoted 7 lines
drivers/block/sata_loopback.c new file +7 -0
+				printf("File index %d is out of range.\n", dev);
+				return -EINVAL;
+			}
+			free(filenames[dev]);
+			filenames[dev] = strdup(argv[3]);
+			init_sata(dev);
+			return scan_sata(dev);

drivers/block/sata_loopback.c line 198

Quoted 10 lines
drivers/block/sata_loopback.c new file +10 -0
+		}
+		return CMD_RET_USAGE;
+	}
+	return CMD_RET_USAGE;
+}
+
+U_BOOT_CMD(
+	sata_loop, 4, 1, do_loop,
+	"SATA loopback",
+	"[info] devnum - show info about loop devnum\n"

Make this "info" part mandatory. Than you can cut the whole argc loop into simple "if argc != 2 ; then fail" . And do simple checking for the first letter of the argument being either i or d .

Quoted 2 lines
(quoted diff) +1 -0
+	"sata_loop load devnum file - load file from host FS into loop

devnum"

sata_loop is redundant above.

Quoted 1 line

+);

#26 lore raw

PATCH v3 1/2 Loop block device for sandbox

Quoted 15 lines · On Wednesday 05 of September 2012 14:48:40 Marek Vasut wrote:

Dear Pavel Herrmann,

[...]

Quoted 5 lines
Quoted 2 lines

besides, I think it'd be much systematic to just scream at user to call "sata rescan" and bail out instead of doing it for him.

i dont actually need a sata rescan, i just need to make sure i have dynamically allocated names

Sorry, I can't parse this ... but ...

Quoted 2 lines

, so i can safely call free() later, otherwise
this segfaults when called before sata scan

Quoted 7 lines

The free() function frees the memory space pointed to by ptr, which must have been returned by a previous call to malloc(), calloc() or realloc(). Otherwise, or if free(ptr) has already been called before, undefined behavior occurs. If ptr is NULL, no operation is performed.

So if you call free() on null pointer, nothing happens. Where's the real problem?

if you called "sata init" before setting all the loops you would get to open(NULL) and a strlen(NULL). i think its easier to supply valid empty string then check for NULL at every access.

Quoted 8 lines
Quoted 6 lines
Quoted 4 lines

Make this "info" part mandatory. Than you can cut the whole argc loop into simple "if argc != 2 ; then fail" . And do simple checking for the first letter of the argument being either i or d .

wont help, still need argc 3 or 4

Makes is simpler, you can bail out if it's not 3 or 4

still, i should have a "sata_loop info" work on all files, so theres a valid command with argc 2

Quoted 8 lines
Quoted 6 lines
Quoted 4 lines
Quoted 2 lines
(quoted diff) +1 -0
+	"sata_loop load devnum file - load file from host FS into loop

devnum"

sata_loop is redundant above.

really? how do you figure?

Run "help sata_loop" and see the result ...

=>help sata_loop
sata_loop - SATA loopback

Usage:
sata_loop [info] devnum - show info about loop devnum sata_loop load devnum file - load file from host FS into loop devnum

i dont see your problem

Pavel Herrmann

#27 lore raw

PATCH v3 1/2 Loop block device for sandbox

Dear Pavel Herrmann,

Quoted 21 lines · On Wednesday 05 of September 2012 14:48:40 Marek Vasut wrote:
Quoted 20 lines

Dear Pavel Herrmann,

[...]

Quoted 5 lines
Quoted 2 lines

besides, I think it'd be much systematic to just scream at user to call "sata rescan" and bail out instead of doing it for him.

i dont actually need a sata rescan, i just need to make sure i have dynamically allocated names

Sorry, I can't parse this ... but ...

Quoted 2 lines

, so i can safely call free() later, otherwise
this segfaults when called before sata scan

The free() function frees the memory space pointed to by ptr, which must have been returned by a previous call to malloc(), calloc() or realloc(). Otherwise, or if free(ptr) has already been called before, undefined behavior occurs. If ptr is NULL, no operation is performed.

Quoted 6 lines
Quoted 2 lines

So if you call free() on null pointer, nothing happens. Where's the real problem?

if you called "sata init" before setting all the loops you would get to open(NULL) and a strlen(NULL). i think its easier to supply valid empty string then check for NULL at every access.

I'd say check for null on every access ... you'd lower memory requirements and the increase in code requirement should really be very minor. Also, it'd remove the "zeroed" static variable altogether, correct?

Quoted 10 lines
Quoted 7 lines
Quoted 5 lines
Quoted 3 lines

Make this "info" part mandatory. Than you can cut the whole argc loop into simple "if argc != 2 ; then fail" . And do simple checking for the first letter of the argument being either i or d .

wont help, still need argc 3 or 4

Makes is simpler, you can bail out if it's not 3 or 4

still, i should have a "sata_loop info" work on all files, so theres a valid command with argc 2

Understood.

Quoted 9 lines
Quoted 8 lines
Quoted 6 lines
Quoted 4 lines
Quoted 2 lines
(quoted diff) +1 -0
+	"sata_loop load devnum file - load file from host FS into loop

devnum"

sata_loop is redundant above.

really? how do you figure?

Run "help sata_loop" and see the result ...

Quoted 8 lines

=>help sata_loop
sata_loop - SATA loopback

Usage:
sata_loop [info] devnum - show info about loop devnum sata_loop load devnum file - load file from host FS into loop devnum

i dont see your problem

Ewww ... nevermind ... I just detected yet another stupid issue in the codebase. I'd say this "sata_loop" should be either omitted and filled by the macro or something. But that's for other time to solve ... so I'm fine with this now.

Quoted 1 line

Pavel Herrmann

Best regards,
Marek Vasut

#28 lore raw

PATCH v3 1/2 Loop block device for sandbox

Quoted 27 lines · On Thursday 06 of September 2012 03:08:42 Marek Vasut wrote:

Dear Pavel Herrmann,

Quoted 25 lines · On Wednesday 05 of September 2012 14:48:40 Marek Vasut wrote:
Quoted 23 lines

Dear Pavel Herrmann,

[...]

Quoted 5 lines
Quoted 2 lines

besides, I think it'd be much systematic to just scream at user to call "sata rescan" and bail out instead of doing it for him.

i dont actually need a sata rescan, i just need to make sure i have dynamically allocated names

Sorry, I can't parse this ... but ...

Quoted 2 lines

, so i can safely call free() later, otherwise
this segfaults when called before sata scan

The free() function frees the memory space pointed to by ptr, which must have been returned by a previous call to malloc(), calloc() or realloc().
Otherwise, or if free(ptr) has already been called before, undefined behavior occurs. If ptr is NULL, no operation is performed.

So if you call free() on null pointer, nothing happens. Where's the real problem?

Quoted 7 lines
Quoted 3 lines

if you called "sata init" before setting all the loops you would get to open(NULL) and a strlen(NULL). i think its easier to supply valid empty string then check for NULL at every access.

I'd say check for null on every access ... you'd lower memory requirements and the increase in code requirement should really be very minor. Also, it'd remove the "zeroed" static variable altogether, correct?

OK, fine by me

Quoted 30 lines
Quoted 11 lines
Quoted 8 lines
Quoted 6 lines
Quoted 4 lines

Make this "info" part mandatory. Than you can cut the whole argc loop
into simple "if argc != 2 ; then fail" . And do simple checking for the first letter of the argument being either i or d .

wont help, still need argc 3 or 4

Makes is simpler, you can bail out if it's not 3 or 4

still, i should have a "sata_loop info" work on all files, so theres a valid command with argc 2

Understood.

Quoted 16 lines
Quoted 8 lines
Quoted 6 lines
Quoted 4 lines
Quoted 2 lines
(quoted diff) +1 -0
+	"sata_loop load devnum file - load file from host FS into loop

devnum"

sata_loop is redundant above.

really? how do you figure?

Run "help sata_loop" and see the result ...

=>help sata_loop
sata_loop - SATA loopback

Usage:
sata_loop [info] devnum - show info about loop devnum sata_loop load devnum file - load file from host FS into loop devnum

Quoted 6 lines
Quoted 1 line

i dont see your problem

Ewww ... nevermind ... I just detected yet another stupid issue in the codebase. I'd say this "sata_loop" should be either omitted and filled by the macro or something. But that's for other time to solve ... so I'm fine with this now.

it actually is, but only to the first line (as both lines are in one string). In my opinion it should either add this for each line (with some magic string modification) or none at all, to keep it consistent

Pavel Herrmann

#29 lore raw

PATCH v3 1/2 Loop block device for sandbox

Dear Pavel Herrmann,

Quoted 71 lines · On Thursday 06 of September 2012 03:08:42 Marek Vasut wrote:
Quoted 27 lines

Dear Pavel Herrmann,

Quoted 25 lines · On Wednesday 05 of September 2012 14:48:40 Marek Vasut wrote:
Quoted 23 lines

Dear Pavel Herrmann,

[...]

Quoted 5 lines
Quoted 2 lines

besides, I think it'd be much systematic to just scream at user to call "sata rescan" and bail out instead of doing it for him.

i dont actually need a sata rescan, i just need to make sure i have dynamically allocated names

Sorry, I can't parse this ... but ...

Quoted 2 lines

, so i can safely call free() later, otherwise
this segfaults when called before sata scan

The free() function frees the memory space pointed to by ptr, which must have been returned by a previous call to malloc(), calloc() or realloc().
Otherwise, or if free(ptr) has already been called before, undefined behavior occurs. If ptr is NULL, no operation is performed.

So if you call free() on null pointer, nothing happens. Where's the real problem?

Quoted 8 lines
Quoted 3 lines

if you called "sata init" before setting all the loops you would get to open(NULL) and a strlen(NULL). i think its easier to supply valid empty string then check for NULL at every access.

I'd say check for null on every access ... you'd lower memory requirements and the increase in code requirement should really be very minor. Also, it'd remove the "zeroed" static variable altogether, correct?

OK, fine by me

Quoted 32 lines
Quoted 11 lines
Quoted 8 lines
Quoted 6 lines
Quoted 4 lines

Make this "info" part mandatory. Than you can cut the whole argc loop
into simple "if argc != 2 ; then fail" . And do simple checking for the first letter of the argument being either i or d .

wont help, still need argc 3 or 4

Makes is simpler, you can bail out if it's not 3 or 4

still, i should have a "sata_loop info" work on all files, so theres a valid command with argc 2

Understood.

Quoted 17 lines
Quoted 8 lines
Quoted 6 lines
Quoted 4 lines
Quoted 2 lines
(quoted diff) +1 -0
+	"sata_loop load devnum file - load file from host FS into

loop devnum"

sata_loop is redundant above.

really? how do you figure?

Run "help sata_loop" and see the result ...

=>help sata_loop
sata_loop - SATA loopback

Usage:
sata_loop [info] devnum - show info about loop devnum sata_loop load devnum file - load file from host FS into loop devnum

i dont see your problem

Quoted 8 lines
Quoted 4 lines

Ewww ... nevermind ... I just detected yet another stupid issue in the codebase. I'd say this "sata_loop" should be either omitted and filled by the macro or something. But that's for other time to solve ... so I'm fine with this now.

it actually is, but only to the first line (as both lines are in one string). In my opinion it should either add this for each line (with some magic string modification) or none at all, to keep it consistent

Keep it as is now, but it's something that should eventually be resolved.

Quoted 1 line

Pavel Herrmann

#30 lore raw

PATCH v3 1/2 Loop block device for sandbox

In reply to Marek Vasut

second try...

Quoted 35 lines · On Wednesday 05 September 2012 13:33:13 Marek Vasut wrote:

Dear Pavel Herrmann,

Quoted 7 lines

This driver uses files as block devices, can be used for testing disk operations on sandbox.
A new command "sata_loop" is introduced to load files in runtime.

CC Marek Vasut <[email protected]>
CC Mike Frysinger <[email protected]>

ERROR: "foo * bar" should be "foo *bar"
#136: FILE: drivers/block/sata_loopback.c:36:
+static char * filenames[CONFIG_SYS_SATA_MAX_DEVICE];

WARNING: externs should be avoided in .c files
#138: FILE: drivers/block/sata_loopback.c:38:
+extern block_dev_desc_t sata_dev_desc[];

ERROR: do not initialise statics to 0 or NULL
#142: FILE: drivers/block/sata_loopback.c:42:
+ static int zeroed = 0;

ERROR: spaces required around that '=' (ctx:VxV)
#150: FILE: drivers/block/sata_loopback.c:50:

+                       filenames[i]=strdup("");
                                    ^

ERROR: space prohibited after that open parenthesis '(' #181: FILE: drivers/block/sata_loopback.c:81:
+ if ( os_lseek(fd, start_byte, OS_SEEK_SET) != start_byte)

ERROR: space prohibited after that open parenthesis '(' #197: FILE: drivers/block/sata_loopback.c:97:
+ if ( os_lseek(fd, start_byte, OS_SEEK_SET) != start_byte)

Quoted 8 lines

ERROR: do not initialise statics to 0 or NULL
#256: FILE: drivers/block/sata_loopback.c:156:
+ static int zeroed = 0;

total: 6 errors, 1 warnings, 207 lines checked

Checkpatch and I never sleep, don't even try ;-)

sorry, my bad, i thought i had it on pre-commit

Quoted 77 lines
Quoted 77 lines

---

Changes for v3:
introduce sata_loop command

Changes for v2:
split sandbox config off into separate patch (2/2) rename file to signify exported API
style fixes
show end of long filenames rather than beginning check for lseek errors to indicate non-regular file

 drivers/block/Makefile        |   1 +
 drivers/block/sata_loopback.c | 200

++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 201 insertions(+)

 create mode 100644 drivers/block/sata_loopback.c
drivers/block/Makefile +1 -0
index f1ebdcc..c95651a 100644
@@ -40,6 +40,7 @@ COBJS-$(CONFIG_SATA_SIL) += sata_sil.o
 
 COBJS-$(CONFIG_IDE_SIL680) += sil680.o
 COBJS-$(CONFIG_SCSI_SYM53C8XX) += sym53c8xx.o
 COBJS-$(CONFIG_SYSTEMACE) += systemace.o
 
+COBJS-${CONFIG_SATA_LOOP} += sata_loopback.o
 

COBJS := $(COBJS-y)
SRCS := $(COBJS:.o=.c)

drivers/block/sata_loopback.c new file +36 -0
new file mode 100644
index 0000000..0e6923b
@@ -0,0 +1,200 @@
+/*
+ * (C) Copyright 2012
+ * Pavel Herrmann <[email protected]>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <part.h>
+#include <ata.h>
+#include <libata.h>
+#include <errno.h>
+#include <os.h>
+#include <command.h>
+#include <malloc.h>
+
+static const char revision[] = "0.0";
+static const char vendor[] = "SATA loopback";
+
+static char * filenames[CONFIG_SYS_SATA_MAX_DEVICE];
Quoted 8 lines

drivers/block/sata_loopback.c line 42

Quoted 6 lines
drivers/block/sata_loopback.c new file +6 -0
+
+extern block_dev_desc_t sata_dev_desc[];
+
+int init_sata(int dev)
+{
+	static int zeroed = 0;

Is this really needed here and below? Pull this crap out.

yes, because you dont know whether this gets called first from sata_loop or from "sata init"

Quoted 55 lines
Quoted 42 lines
drivers/block/sata_loopback.c new file +42 -0
+int scan_sata(int dev)
+{
+	block_dev_desc_t *pdev = &sata_dev_desc[dev];
+	int fd = (long) pdev->priv;
+	int namelen;
+	const char *filename = filenames[dev];
+	lbaint_t bytes = 0;
+
+	if ((dev < 0) || (dev >= CONFIG_SYS_SATA_MAX_DEVICE)) {
+		printf("File index %d is out of range.\n", dev);
+		return -EINVAL;
+	}
+
+	memcpy(pdev->vendor, vendor, sizeof(vendor));
+	memcpy(pdev->revision, revision, sizeof(revision));
+	namelen = strlen(filenames[dev]);
+
+	if (namelen > 20) {
+		/* take the last 17 chars, prepend them with "..." */
+		filename += (namelen - 17);
+		memcpy(pdev->product, "...", 3);
+		memcpy(pdev->product+3, filename, 17);
+	} else
+		memcpy(pdev->product, filename, namelen);
+
+	pdev->product[20] = 0;
+
+	bytes = os_lseek(fd, 0, OS_SEEK_END);
+	if (bytes != -1) {
+		pdev->type = DEV_TYPE_HARDDISK;
+		pdev->blksz = ATA_SECT_SIZE;
+		pdev->lun = 0;
+		pdev->lba = bytes/ATA_SECT_SIZE;
+		printf("SATA loop %d:\nfilename: %s\nsize: %lu\nblock count:"
+			" %lu\n", dev, filenames[dev], bytes, pdev->lba);
+	} else {
+		pdev->type = DEV_TYPE_HARDDISK;
+		pdev->blksz = ATA_SECT_SIZE;
+		pdev->lun = 0;
+		pdev->lba = 0;
+		printf("SATA loop %d:\nfilename: %s\nFAILED TO OPEN\n",
+			 dev, filenames[dev]);

drivers/block/sata_loopback.c line 156

Quoted 10 lines
drivers/block/sata_loopback.c new file +10 -0
+	}
+
+	return 0;
+}
+
+
+int do_loop(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	int dev = 0;
+	static int zeroed = 0;

move this out.

Quoted 2 lines

besides, I think it'd be much systematic to just scream at user to call "sata rescan" and bail out instead of doing it for him.

i dont actually need a sata rescan, i just need to make sure i have dynamically allocated names, so i can safely call free() later, otherwise this segfaults when called before sata scan

Quoted 7 lines
Quoted 7 lines
drivers/block/sata_loopback.c new file +7 -0
+	/* make sure we have valid filenames */
+	if (!zeroed) {
+		init_sata(0);
+		zeroed = 1;
+	}
+
+	switch (argc) {
Quoted 8 lines

drivers/block/sata_loopback.c line 169

Quoted 5 lines
drivers/block/sata_loopback.c new file +5 -0
+	case 0:
+	case 1:
+		return CMD_RET_USAGE;
+	case 2:
+		dev = simple_strtoul(argv[1], NULL, 10);

Ok, so if I run this command and ask for device 0xb00bf33d ... will this survive? Hint: it won't, rangecheck missing.

hint - scan_sata does the range check in this codepath

Quoted 7 lines

drivers/block/sata_loopback.c line 174

Quoted 5 lines
drivers/block/sata_loopback.c new file +5 -0
+		return scan_sata(dev);
+
+	case 3:
+		if (!strncmp(argv[1], "inf", 3)) {
+			dev = simple_strtoul(argv[2], NULL, 10);

Same here

see above

Quoted 26 lines

drivers/block/sata_loopback.c line 181

Quoted 7 lines
drivers/block/sata_loopback.c new file +7 -0
+			return scan_sata(dev);
+		}
+		return CMD_RET_USAGE;
+	case 4:
+		if (!strncmp(argv[1], "load", 4)) {
+			dev = simple_strtoul(argv[2], NULL, 10);
+			if ((dev < 0) || (dev >= CONFIG_SYS_SATA_MAX_DEVICE)) {

And here you have it ?

Uh oh, I see, sata_scan() does it for you ... I'd say, abstract it out into lightweight static inline function.

Quoted 13 lines
drivers/block/sata_loopback.c new file +13 -0
+				printf("File index %d is out of range.\n", dev);
+				return -EINVAL;
+			}
+			free(filenames[dev]);
+			filenames[dev] = strdup(argv[3]);
+			init_sata(dev);
+			return scan_sata(dev);
+		}
+		return CMD_RET_USAGE;
+	}
+	return CMD_RET_USAGE;
+}
+
Quoted 8 lines

drivers/block/sata_loopback.c line 198

Quoted 4 lines
drivers/block/sata_loopback.c new file +4 -0
+U_BOOT_CMD(
+	sata_loop, 4, 1, do_loop,
+	"SATA loopback",
+	"[info] devnum - show info about loop devnum\n"

Make this "info" part mandatory. Than you can cut the whole argc loop into simple "if argc != 2 ; then fail" . And do simple checking for the first letter of the argument being either i or d .

wont help, still need argc 3 or 4

Quoted 3 lines

drivers/block/sata_loopback.c line 199

Quoted 1 line
drivers/block/sata_loopback.c new file +1 -0
+	"sata_loop load devnum file - load file from host FS into loop devnum"

sata_loop is redundant above.

really? how do you figure?

Pavel Herrmann

#31 lore raw

PATCH v3 1/2 Loop block device for sandbox

Dear Pavel Herrmann,

[...]

Quoted 9 lines
Quoted 5 lines

move this out.

besides, I think it'd be much systematic to just scream at user to call "sata rescan" and bail out instead of doing it for him.

i dont actually need a sata rescan, i just need to make sure i have dynamically allocated names, so i can safely call free() later, otherwise this segfaults when called before sata scan

See my previous email

Quoted 16 lines
Quoted 7 lines
Quoted 7 lines
drivers/block/sata_loopback.c new file +7 -0
+	/* make sure we have valid filenames */
+	if (!zeroed) {
+		init_sata(0);
+		zeroed = 1;
+	}
+
+	switch (argc) {
Quoted 8 lines

drivers/block/sata_loopback.c line 169

Quoted 5 lines
drivers/block/sata_loopback.c new file +5 -0
+	case 0:
+	case 1:
+		return CMD_RET_USAGE;
+	case 2:
+		dev = simple_strtoul(argv[1], NULL, 10);

Ok, so if I run this command and ask for device 0xb00bf33d ... will this survive? Hint: it won't, rangecheck missing.

Quoted 1 line

hint - scan_sata does the range check in this codepath

saw it, see below. Duplication of code is not good and is error prone.

Quoted 45 lines
Quoted 7 lines

drivers/block/sata_loopback.c line 174

Quoted 5 lines
drivers/block/sata_loopback.c new file +5 -0
+		return scan_sata(dev);
+
+	case 3:
+		if (!strncmp(argv[1], "inf", 3)) {
+			dev = simple_strtoul(argv[2], NULL, 10);

Same here

see above

Quoted 26 lines

drivers/block/sata_loopback.c line 181

Quoted 7 lines
drivers/block/sata_loopback.c new file +7 -0
+			return scan_sata(dev);
+		}
+		return CMD_RET_USAGE;
+	case 4:
+		if (!strncmp(argv[1], "load", 4)) {
+			dev = simple_strtoul(argv[2], NULL, 10);
+			if ((dev < 0) || (dev >= CONFIG_SYS_SATA_MAX_DEVICE)) {

And here you have it ?

Uh oh, I see, sata_scan() does it for you ... I'd say, abstract it out into lightweight static inline function.

Quoted 13 lines
drivers/block/sata_loopback.c new file +13 -0
+				printf("File index %d is out of range.\n", dev);
+				return -EINVAL;
+			}
+			free(filenames[dev]);
+			filenames[dev] = strdup(argv[3]);
+			init_sata(dev);
+			return scan_sata(dev);
+		}
+		return CMD_RET_USAGE;
+	}
+	return CMD_RET_USAGE;
+}
+
Quoted 8 lines

drivers/block/sata_loopback.c line 198

Quoted 4 lines
drivers/block/sata_loopback.c new file +4 -0
+U_BOOT_CMD(
+	sata_loop, 4, 1, do_loop,
+	"SATA loopback",
+	"[info] devnum - show info about loop devnum\n"

Make this "info" part mandatory. Than you can cut the whole argc loop into simple "if argc != 2 ; then fail" . And do simple checking for the first letter of the argument being either i or d .

Quoted 1 line

wont help, still need argc 3 or 4

Makes is simpler, you can bail out if it's not 3 or 4

Quoted 6 lines
Quoted 4 lines
Quoted 2 lines
(quoted diff) +1 -0
+	"sata_loop load devnum file - load file from host FS into loop

devnum"

sata_loop is redundant above.

really? how do you figure?

Run "help sata_loop" and see the result ...

Quoted 2 lines

Pavel Herrmann

#32 lore raw

PATCH v4 1/2 Loop block device for sandbox

In reply to Pavel Herrmann

This driver uses files as block devices, can be used for testing disk operations on sandbox.
A new command "sata_loop" is introduced to load files in runtime.

CC Marek Vasut <[email protected]>
CC Mike Frysinger <[email protected]>

---
Changes for v4:
checkpatch fixes
use NULLs instead of ""
extend sata_loop command

Changes for v3:
introduce sata_loop command

Changes for v2:
split sandbox config off into separate patch (2/2) rename file to signify exported API
style fixes
show end of long filenames rather than beginning check for lseek errors to indicate non-regular file

 drivers/block/Makefile        |   1 +
 drivers/block/sata_loopback.c | 212 ++++++++++++++++++++++++++++++++++++++++++
 include/configs/sandbox.h     |   8 ++
 3 files changed, 221 insertions(+)
 create mode 100644 drivers/block/sata_loopback.c
drivers/block/Makefile +1 -0
index f1ebdcc..c95651a 100644
@@ -40,6 +40,7 @@ COBJS-$(CONFIG_SATA_SIL) += sata_sil.o
 COBJS-$(CONFIG_IDE_SIL680) += sil680.o
 COBJS-$(CONFIG_SCSI_SYM53C8XX) += sym53c8xx.o
 COBJS-$(CONFIG_SYSTEMACE) += systemace.o
+COBJS-${CONFIG_SATA_LOOP} += sata_loopback.o
 
 COBJS	:= $(COBJS-y)
 SRCS	:= $(COBJS:.o=.c)
drivers/block/sata_loopback.c new file +212 -0

212 lines not on this page · raw message

include/configs/sandbox.h +8 -0
index 0220386..a713430 100644
@@ -93,4 +93,12 @@
 					"stdout=serial\0" \
 					"stderr=serial\0"
 
+/* SATA loopback device */
+#define CONFIG_CMD_SATA
+#define CONFIG_SATA_LOOP
+#define CONFIG_SYS_SATA_MAX_DEVICE 2
+#define CONFIG_DOS_PARTITION
+#define CONFIG_CMD_FAT
+#define CONFIG_CMD_EXT2
+
 #endif
Signature · 1 line
1.7.12
#33 lore raw

PATCH v4 1/2 Loop block device for sandbox

Dear Pavel Herrmann,

Quoted 3 lines

This driver uses files as block devices, can be used for testing disk operations on sandbox.
A new command "sata_loop" is introduced to load files in runtime.

WARNING: externs should be avoided in .c files
#141: FILE: drivers/block/sata_loopback.c:39:
+extern block_dev_desc_t sata_dev_desc[];

total: 0 errors, 1 warnings, 231 lines checked

NOTE: Ignored message types: COMPLEX_MACRO CONSIDER_KSTRTO MINMAX MULTISTATEMENT_MACRO_USE_DO_WHILE

Quoted 273 lines
CC Marek Vasut <[email protected]>
CC Mike Frysinger <[email protected]>

---
Changes for v4:
checkpatch fixes
use NULLs instead of ""
extend sata_loop command

Changes for v3:
introduce sata_loop command

Changes for v2:
split sandbox config off into separate patch (2/2) rename file to signify exported API
style fixes
show end of long filenames rather than beginning check for lseek errors to indicate non-regular file

 drivers/block/Makefile        |   1 +
 drivers/block/sata_loopback.c | 212
++++++++++++++++++++++++++++++++++++++++++ include/configs/sandbox.h     |
  8 ++
 3 files changed, 221 insertions(+)
 create mode 100644 drivers/block/sata_loopback.c
drivers/block/Makefile +1 -0
index f1ebdcc..c95651a 100644
@@ -40,6 +40,7 @@ COBJS-$(CONFIG_SATA_SIL) += sata_sil.o
 COBJS-$(CONFIG_IDE_SIL680) += sil680.o
 COBJS-$(CONFIG_SCSI_SYM53C8XX) += sym53c8xx.o
 COBJS-$(CONFIG_SYSTEMACE) += systemace.o
+COBJS-${CONFIG_SATA_LOOP} += sata_loopback.o
 
 COBJS	:= $(COBJS-y)
 SRCS	:= $(COBJS:.o=.c)
drivers/block/sata_loopback.c new file +87 -0
new file mode 100644
index 0000000..600fbdc
@@ -0,0 +1,212 @@
+/*
+ * (C) Copyright 2012
+ * Pavel Herrmann <[email protected]>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <part.h>
+#include <ata.h>
+#include <libata.h>
+#include <errno.h>
+#include <os.h>
+#include <command.h>
+#include <malloc.h>
+
+static const char revision[] = "0.0";
+static const char vendor[] = "SATA loopback";
+
+/* this will be auto-initialized to NULLs */
+static char *filenames[CONFIG_SYS_SATA_MAX_DEVICE];
+
+extern block_dev_desc_t sata_dev_desc[];
+
+static inline int range_check(int dev)
+{
+	return  (dev < 0) || (dev >= CONFIG_SYS_SATA_MAX_DEVICE);
+}
+
+int init_sata(int dev)
+{
+	block_dev_desc_t *pdev = &sata_dev_desc[dev];
+	int fd, old_fd;
+
+	if (range_check(dev)) {
+		printf("File index %d is out of range.\n", dev);
+		return -EINVAL;
+	}
+
+	if (filenames[dev])
+		fd = os_open(filenames[dev], OS_O_RDWR);
+	else
+		fd = -1;
+
+	old_fd = (long) pdev->priv;
+	/* This is ugly, but saves allocation for 1 int. */
+	pdev->priv = (void *) (long) fd;
+
+	if ((old_fd > 2) || (old_fd < 0))
+		os_close(old_fd);
+
+	return 0;
+}
+
+lbaint_t sata_read(int dev, lbaint_t start, lbaint_t blkcnt, void *buffer)
+{
+	block_dev_desc_t *pdev = &sata_dev_desc[dev];
+	int fd = (long) pdev->priv;
+	lbaint_t start_byte = ATA_SECT_SIZE * start;
+	lbaint_t length_byte = ATA_SECT_SIZE * blkcnt;
+	lbaint_t retval;
+
+	if (os_lseek(fd, start_byte, OS_SEEK_SET) != start_byte)
+		return -1;
+
+	retval = os_read(fd, buffer, length_byte);
+
+	return retval / ATA_SECT_SIZE;
+}
+
+lbaint_t sata_write(int dev, lbaint_t start, lbaint_t blkcnt, void

*buffer) +{

drivers/block/sata_loopback.c new file +124 -0
+	block_dev_desc_t *pdev = &sata_dev_desc[dev];
+	int fd = (long) pdev->priv;
+	lbaint_t start_byte = ATA_SECT_SIZE * start;
+	lbaint_t length_byte = ATA_SECT_SIZE * blkcnt;
+	lbaint_t retval;
+
+	if (os_lseek(fd, start_byte, OS_SEEK_SET) != start_byte)
+		return -1;
+
+	retval = os_write(fd, buffer, length_byte);
+
+	return retval / ATA_SECT_SIZE;
+}
+
+int scan_sata(int dev)
+{
+	block_dev_desc_t *pdev = &sata_dev_desc[dev];
+	int fd = (long) pdev->priv;
+	int namelen;
+	char *filename;
+	lbaint_t bytes = 0;
+
+	if (range_check(dev)) {
+		printf("File index %d is out of range.\n", dev);
+		return -EINVAL;
+	}
+
+	if (filenames[dev])
+		filename = filenames[dev];
+	else
+		filename = "";
+
+	memcpy(pdev->vendor, vendor, sizeof(vendor));
+	memcpy(pdev->revision, revision, sizeof(revision));
+	namelen = strlen(filename);
+
+	if (namelen > 20) {
+		/* take the last 17 chars, prepend them with "..." */
+		memcpy(pdev->product, "...", 3);
+		memcpy(pdev->product+3, filename + (namelen - 17), 17);
+	} else
+		memcpy(pdev->product, filename, namelen);
+
+	pdev->product[20] = 0;
+
+	bytes = os_lseek(fd, 0, OS_SEEK_END);
+	if (bytes != -1) {
+		pdev->type = DEV_TYPE_HARDDISK;
+		pdev->blksz = ATA_SECT_SIZE;
+		pdev->lun = 0;
+		pdev->lba = bytes/ATA_SECT_SIZE;
+		printf("SATA loop %d:\nfilename: %s\nsize: %lu\nblock count:"
+			" %lu\n", dev, filename, bytes, pdev->lba);
+	} else {
+		pdev->type = DEV_TYPE_HARDDISK;
+		pdev->blksz = ATA_SECT_SIZE;
+		pdev->lun = 0;
+		pdev->lba = 0;
+		printf("SATA loop %d:\nfilename: %s\nFAILED TO OPEN\n",
+			 dev, filename);
+	}
+
+	return 0;
+}
+
+
+int do_loop(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	int dev = 0;
+
+	switch (argc) {
+	case 0:
+	case 1:
+		return CMD_RET_USAGE;
+	case 2:
+		if (!strncmp(argv[1], "inf", 3)) {
+			for (dev = 0; dev < CONFIG_SYS_SATA_MAX_DEVICE; dev++)
+				scan_sata(dev);
+			return 0;
+		}
+		return CMD_RET_USAGE;
+	case 3:
+		if (!strncmp(argv[1], "inf", 3)) {
+			dev = simple_strtoul(argv[2], NULL, 10);
+			return scan_sata(dev);
+		}
+		return CMD_RET_USAGE;
+	case 4:
+		if (!strncmp(argv[1], "load", 4)) {
+			dev = simple_strtoul(argv[2], NULL, 10);
+			/*
+			 * init_sata() and scan_sata() do their own range
+			 * check, however we need to explicitly do it here
+			 * as well.
+			 */
+			if (range_check(dev)) {
+				printf("File index %d is out of range.\n", dev);
+				return -EINVAL;
+			}
+			free(filenames[dev]);
+			filenames[dev] = strdup(argv[3]);
+			init_sata(dev);
+			scan_sata(dev);
+			/*
+			 * Scan the partition table if we succeeded in loading
+			 * the new loop file.
+			 */
+			if (sata_dev_desc[dev].lba > 0)
+				init_part(&sata_dev_desc[dev]);
+
+			return 0;
+		}
+		return CMD_RET_USAGE;
+	}
+	return CMD_RET_USAGE;
+}
+
+U_BOOT_CMD(
+	sata_loop, 4, 1, do_loop,
+	"SATA loopback",
+	"info - show info about all loop devices\n"
+	"sata_loop info devnum - show info about loop devnum\n"
+	"sata_loop load devnum file - load file from host FS into loop devnum"
+);
include/configs/sandbox.h +8 -0
index 0220386..a713430 100644
@@ -93,4 +93,12 @@
 					"stdout=serial\0" \
 					"stderr=serial\0"
 
+/* SATA loopback device */
+#define CONFIG_CMD_SATA
+#define CONFIG_SATA_LOOP
+#define CONFIG_SYS_SATA_MAX_DEVICE 2
+#define CONFIG_DOS_PARTITION
+#define CONFIG_CMD_FAT
+#define CONFIG_CMD_EXT2
+
 #endif
#34 lore raw

PATCH v4 1/2 Loop block device for sandbox

Quoted 6 lines · On Friday 07 of September 2012 01:29:55 Marek Vasut wrote:

Dear Pavel Herrmann,

Quoted 3 lines

This driver uses files as block devices, can be used for testing disk operations on sandbox.
A new command "sata_loop" is introduced to load files in runtime.

Quoted 8 lines

WARNING: externs should be avoided in .c files
#141: FILE: drivers/block/sata_loopback.c:39:
+extern block_dev_desc_t sata_dev_desc[];

total: 0 errors, 1 warnings, 231 lines checked

NOTE: Ignored message types: COMPLEX_MACRO CONSIDER_KSTRTO MINMAX MULTISTATEMENT_MACRO_USE_DO_WHILE

Yes, i know about that, and chose to ignore it.
i will not create a header file for a single line that checkpatch doesnt like (with just a warning), especially when other drivers have such a line in them as well.

Quoted 283 lines
Quoted 283 lines
CC Marek Vasut <[email protected]>
CC Mike Frysinger <[email protected]>

---

Changes for v4:
checkpatch fixes
use NULLs instead of ""
extend sata_loop command

Changes for v3:
introduce sata_loop command

Changes for v2:
split sandbox config off into separate patch (2/2) rename file to signify exported API
style fixes
show end of long filenames rather than beginning check for lseek errors to indicate non-regular file

 drivers/block/Makefile        |   1 +
 drivers/block/sata_loopback.c | 212

++++++++++++++++++++++++++++++++++++++++++ include/configs/sandbox.h |

8 ++

 3 files changed, 221 insertions(+)
 create mode 100644 drivers/block/sata_loopback.c
drivers/block/Makefile +1 -0
index f1ebdcc..c95651a 100644
@@ -40,6 +40,7 @@ COBJS-$(CONFIG_SATA_SIL) += sata_sil.o
 
 COBJS-$(CONFIG_IDE_SIL680) += sil680.o
 COBJS-$(CONFIG_SCSI_SYM53C8XX) += sym53c8xx.o
 COBJS-$(CONFIG_SYSTEMACE) += systemace.o
 
+COBJS-${CONFIG_SATA_LOOP} += sata_loopback.o
 

COBJS := $(COBJS-y)
SRCS := $(COBJS:.o=.c)

drivers/block/sata_loopback.c new file +71 -0
new file mode 100644
index 0000000..600fbdc
@@ -0,0 +1,212 @@
+/*
+ * (C) Copyright 2012
+ * Pavel Herrmann <[email protected]>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <part.h>
+#include <ata.h>
+#include <libata.h>
+#include <errno.h>
+#include <os.h>
+#include <command.h>
+#include <malloc.h>
+
+static const char revision[] = "0.0";
+static const char vendor[] = "SATA loopback";
+
+/* this will be auto-initialized to NULLs */
+static char *filenames[CONFIG_SYS_SATA_MAX_DEVICE];
+
+extern block_dev_desc_t sata_dev_desc[];
+
+static inline int range_check(int dev)
+{
+	return  (dev < 0) || (dev >= CONFIG_SYS_SATA_MAX_DEVICE);
+}
+
+int init_sata(int dev)
+{
+	block_dev_desc_t *pdev = &sata_dev_desc[dev];
+	int fd, old_fd;
+
+	if (range_check(dev)) {
+		printf("File index %d is out of range.\n", dev);
+		return -EINVAL;
+	}
+
+	if (filenames[dev])
+		fd = os_open(filenames[dev], OS_O_RDWR);
+	else
+		fd = -1;
+
+	old_fd = (long) pdev->priv;
+	/* This is ugly, but saves allocation for 1 int. */
+	pdev->priv = (void *) (long) fd;
+
+	if ((old_fd > 2) || (old_fd < 0))
+		os_close(old_fd);
+
+	return 0;
+}
+
+lbaint_t sata_read(int dev, lbaint_t start, lbaint_t blkcnt, void

*buffer)

drivers/block/sata_loopback.c new file +16 -0
+{
+	block_dev_desc_t *pdev = &sata_dev_desc[dev];
+	int fd = (long) pdev->priv;
+	lbaint_t start_byte = ATA_SECT_SIZE * start;
+	lbaint_t length_byte = ATA_SECT_SIZE * blkcnt;
+	lbaint_t retval;
+
+	if (os_lseek(fd, start_byte, OS_SEEK_SET) != start_byte)
+		return -1;
+
+	retval = os_read(fd, buffer, length_byte);
+
+	return retval / ATA_SECT_SIZE;
+}
+
+lbaint_t sata_write(int dev, lbaint_t start, lbaint_t blkcnt, void

*buffer) +{

drivers/block/sata_loopback.c new file +124 -0
+	block_dev_desc_t *pdev = &sata_dev_desc[dev];
+	int fd = (long) pdev->priv;
+	lbaint_t start_byte = ATA_SECT_SIZE * start;
+	lbaint_t length_byte = ATA_SECT_SIZE * blkcnt;
+	lbaint_t retval;
+
+	if (os_lseek(fd, start_byte, OS_SEEK_SET) != start_byte)
+		return -1;
+
+	retval = os_write(fd, buffer, length_byte);
+
+	return retval / ATA_SECT_SIZE;
+}
+
+int scan_sata(int dev)
+{
+	block_dev_desc_t *pdev = &sata_dev_desc[dev];
+	int fd = (long) pdev->priv;
+	int namelen;
+	char *filename;
+	lbaint_t bytes = 0;
+
+	if (range_check(dev)) {
+		printf("File index %d is out of range.\n", dev);
+		return -EINVAL;
+	}
+
+	if (filenames[dev])
+		filename = filenames[dev];
+	else
+		filename = "";
+
+	memcpy(pdev->vendor, vendor, sizeof(vendor));
+	memcpy(pdev->revision, revision, sizeof(revision));
+	namelen = strlen(filename);
+
+	if (namelen > 20) {
+		/* take the last 17 chars, prepend them with "..." */
+		memcpy(pdev->product, "...", 3);
+		memcpy(pdev->product+3, filename + (namelen - 17), 17);
+	} else
+		memcpy(pdev->product, filename, namelen);
+
+	pdev->product[20] = 0;
+
+	bytes = os_lseek(fd, 0, OS_SEEK_END);
+	if (bytes != -1) {
+		pdev->type = DEV_TYPE_HARDDISK;
+		pdev->blksz = ATA_SECT_SIZE;
+		pdev->lun = 0;
+		pdev->lba = bytes/ATA_SECT_SIZE;
+		printf("SATA loop %d:\nfilename: %s\nsize: %lu\nblock count:"
+			" %lu\n", dev, filename, bytes, pdev->lba);
+	} else {
+		pdev->type = DEV_TYPE_HARDDISK;
+		pdev->blksz = ATA_SECT_SIZE;
+		pdev->lun = 0;
+		pdev->lba = 0;
+		printf("SATA loop %d:\nfilename: %s\nFAILED TO OPEN\n",
+			 dev, filename);
+	}
+
+	return 0;
+}
+
+
+int do_loop(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	int dev = 0;
+
+	switch (argc) {
+	case 0:
+	case 1:
+		return CMD_RET_USAGE;
+	case 2:
+		if (!strncmp(argv[1], "inf", 3)) {
+			for (dev = 0; dev < CONFIG_SYS_SATA_MAX_DEVICE; dev++)
+				scan_sata(dev);
+			return 0;
+		}
+		return CMD_RET_USAGE;
+	case 3:
+		if (!strncmp(argv[1], "inf", 3)) {
+			dev = simple_strtoul(argv[2], NULL, 10);
+			return scan_sata(dev);
+		}
+		return CMD_RET_USAGE;
+	case 4:
+		if (!strncmp(argv[1], "load", 4)) {
+			dev = simple_strtoul(argv[2], NULL, 10);
+			/*
+			 * init_sata() and scan_sata() do their own range
+			 * check, however we need to explicitly do it here
+			 * as well.
+			 */
+			if (range_check(dev)) {
+				printf("File index %d is out of range.\n", dev);
+				return -EINVAL;
+			}
+			free(filenames[dev]);
+			filenames[dev] = strdup(argv[3]);
+			init_sata(dev);
+			scan_sata(dev);
+			/*
+			 * Scan the partition table if we succeeded in loading
+			 * the new loop file.
+			 */
+			if (sata_dev_desc[dev].lba > 0)
+				init_part(&sata_dev_desc[dev]);
+
+			return 0;
+		}
+		return CMD_RET_USAGE;
+	}
+	return CMD_RET_USAGE;
+}
+
+U_BOOT_CMD(
+	sata_loop, 4, 1, do_loop,
+	"SATA loopback",
+	"info - show info about all loop devices\n"
+	"sata_loop info devnum - show info about loop devnum\n"
+	"sata_loop load devnum file - load file from host FS into loop devnum"
+);
include/configs/sandbox.h +8 -0
index 0220386..a713430 100644
@@ -93,4 +93,12 @@
 
 					"stdout=serial\0" \
 					"stderr=serial\0"
 
+/* SATA loopback device */
+#define CONFIG_CMD_SATA
+#define CONFIG_SATA_LOOP
+#define CONFIG_SYS_SATA_MAX_DEVICE 2
+#define CONFIG_DOS_PARTITION
+#define CONFIG_CMD_FAT
+#define CONFIG_CMD_EXT2
+

#endif

#35 lore raw

PATCH v4 1/2 Loop block device for sandbox

Dear Pavel Herrmann,

Quoted 11 lines · On Friday 07 of September 2012 01:29:55 Marek Vasut wrote:
Quoted 10 lines

Dear Pavel Herrmann,

Quoted 3 lines

This driver uses files as block devices, can be used for testing disk operations on sandbox.
A new command "sata_loop" is introduced to load files in runtime.

WARNING: externs should be avoided in .c files
#141: FILE: drivers/block/sata_loopback.c:39:
+extern block_dev_desc_t sata_dev_desc[];

Quoted 6 lines
Quoted 4 lines

total: 0 errors, 1 warnings, 231 lines checked

NOTE: Ignored message types: COMPLEX_MACRO CONSIDER_KSTRTO MINMAX MULTISTATEMENT_MACRO_USE_DO_WHILE

Yes, i know about that, and chose to ignore it.

Sorry, this is not how it works.

Quoted 3 lines

i will not create a header file for a single line that checkpatch doesnt like (with just a warning), especially when other drivers have such a line in them as well.

So, implement proper accessor for this list? Or export the structure through some sata-related header? How does other do it?

Quoted 284 lines
Quoted 284 lines
Quoted 284 lines
CC Marek Vasut <[email protected]>
CC Mike Frysinger <[email protected]>

---

Changes for v4:
checkpatch fixes
use NULLs instead of ""
extend sata_loop command

Changes for v3:
introduce sata_loop command

Changes for v2:
split sandbox config off into separate patch (2/2) rename file to signify exported API
style fixes
show end of long filenames rather than beginning check for lseek errors to indicate non-regular file

 drivers/block/Makefile        |   1 +
 drivers/block/sata_loopback.c | 212

++++++++++++++++++++++++++++++++++++++++++ include/configs/sandbox.h
|

8 ++

 3 files changed, 221 insertions(+)
 create mode 100644 drivers/block/sata_loopback.c
drivers/block/Makefile +1 -0
index f1ebdcc..c95651a 100644
@@ -40,6 +40,7 @@ COBJS-$(CONFIG_SATA_SIL) += sata_sil.o
 
 COBJS-$(CONFIG_IDE_SIL680) += sil680.o
 COBJS-$(CONFIG_SCSI_SYM53C8XX) += sym53c8xx.o
 COBJS-$(CONFIG_SYSTEMACE) += systemace.o
 
+COBJS-${CONFIG_SATA_LOOP} += sata_loopback.o
 

COBJS := $(COBJS-y)
SRCS := $(COBJS:.o=.c)

(quoted diff) +0 -0

b/drivers/block/sata_loopback.c new file mode 100644 index 0000000..600fbdc

drivers/block/sata_loopback.c new file +71 -0
@@ -0,0 +1,212 @@
+/*
+ * (C) Copyright 2012
+ * Pavel Herrmann <[email protected]>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <part.h>
+#include <ata.h>
+#include <libata.h>
+#include <errno.h>
+#include <os.h>
+#include <command.h>
+#include <malloc.h>
+
+static const char revision[] = "0.0";
+static const char vendor[] = "SATA loopback";
+
+/* this will be auto-initialized to NULLs */
+static char *filenames[CONFIG_SYS_SATA_MAX_DEVICE];
+
+extern block_dev_desc_t sata_dev_desc[];
+
+static inline int range_check(int dev)
+{
+	return  (dev < 0) || (dev >= CONFIG_SYS_SATA_MAX_DEVICE);
+}
+
+int init_sata(int dev)
+{
+	block_dev_desc_t *pdev = &sata_dev_desc[dev];
+	int fd, old_fd;
+
+	if (range_check(dev)) {
+		printf("File index %d is out of range.\n", dev);
+		return -EINVAL;
+	}
+
+	if (filenames[dev])
+		fd = os_open(filenames[dev], OS_O_RDWR);
+	else
+		fd = -1;
+
+	old_fd = (long) pdev->priv;
+	/* This is ugly, but saves allocation for 1 int. */
+	pdev->priv = (void *) (long) fd;
+
+	if ((old_fd > 2) || (old_fd < 0))
+		os_close(old_fd);
+
+	return 0;
+}
+
+lbaint_t sata_read(int dev, lbaint_t start, lbaint_t blkcnt, void

*buffer)

drivers/block/sata_loopback.c new file +16 -0
+{
+	block_dev_desc_t *pdev = &sata_dev_desc[dev];
+	int fd = (long) pdev->priv;
+	lbaint_t start_byte = ATA_SECT_SIZE * start;
+	lbaint_t length_byte = ATA_SECT_SIZE * blkcnt;
+	lbaint_t retval;
+
+	if (os_lseek(fd, start_byte, OS_SEEK_SET) != start_byte)
+		return -1;
+
+	retval = os_read(fd, buffer, length_byte);
+
+	return retval / ATA_SECT_SIZE;
+}
+
+lbaint_t sata_write(int dev, lbaint_t start, lbaint_t blkcnt, void

*buffer) +{

drivers/block/sata_loopback.c new file +123 -0
+	block_dev_desc_t *pdev = &sata_dev_desc[dev];
+	int fd = (long) pdev->priv;
+	lbaint_t start_byte = ATA_SECT_SIZE * start;
+	lbaint_t length_byte = ATA_SECT_SIZE * blkcnt;
+	lbaint_t retval;
+
+	if (os_lseek(fd, start_byte, OS_SEEK_SET) != start_byte)
+		return -1;
+
+	retval = os_write(fd, buffer, length_byte);
+
+	return retval / ATA_SECT_SIZE;
+}
+
+int scan_sata(int dev)
+{
+	block_dev_desc_t *pdev = &sata_dev_desc[dev];
+	int fd = (long) pdev->priv;
+	int namelen;
+	char *filename;
+	lbaint_t bytes = 0;
+
+	if (range_check(dev)) {
+		printf("File index %d is out of range.\n", dev);
+		return -EINVAL;
+	}
+
+	if (filenames[dev])
+		filename = filenames[dev];
+	else
+		filename = "";
+
+	memcpy(pdev->vendor, vendor, sizeof(vendor));
+	memcpy(pdev->revision, revision, sizeof(revision));
+	namelen = strlen(filename);
+
+	if (namelen > 20) {
+		/* take the last 17 chars, prepend them with "..." */
+		memcpy(pdev->product, "...", 3);
+		memcpy(pdev->product+3, filename + (namelen - 17), 17);
+	} else
+		memcpy(pdev->product, filename, namelen);
+
+	pdev->product[20] = 0;
+
+	bytes = os_lseek(fd, 0, OS_SEEK_END);
+	if (bytes != -1) {
+		pdev->type = DEV_TYPE_HARDDISK;
+		pdev->blksz = ATA_SECT_SIZE;
+		pdev->lun = 0;
+		pdev->lba = bytes/ATA_SECT_SIZE;
+		printf("SATA loop %d:\nfilename: %s\nsize: %lu\nblock count:"
+			" %lu\n", dev, filename, bytes, pdev->lba);
+	} else {
+		pdev->type = DEV_TYPE_HARDDISK;
+		pdev->blksz = ATA_SECT_SIZE;
+		pdev->lun = 0;
+		pdev->lba = 0;
+		printf("SATA loop %d:\nfilename: %s\nFAILED TO OPEN\n",
+			 dev, filename);
+	}
+
+	return 0;
+}
+
+
+int do_loop(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	int dev = 0;
+
+	switch (argc) {
+	case 0:
+	case 1:
+		return CMD_RET_USAGE;
+	case 2:
+		if (!strncmp(argv[1], "inf", 3)) {
+			for (dev = 0; dev < CONFIG_SYS_SATA_MAX_DEVICE; dev++)
+				scan_sata(dev);
+			return 0;
+		}
+		return CMD_RET_USAGE;
+	case 3:
+		if (!strncmp(argv[1], "inf", 3)) {
+			dev = simple_strtoul(argv[2], NULL, 10);
+			return scan_sata(dev);
+		}
+		return CMD_RET_USAGE;
+	case 4:
+		if (!strncmp(argv[1], "load", 4)) {
+			dev = simple_strtoul(argv[2], NULL, 10);
+			/*
+			 * init_sata() and scan_sata() do their own range
+			 * check, however we need to explicitly do it here
+			 * as well.
+			 */
+			if (range_check(dev)) {
+				printf("File index %d is out of range.\n", dev);
+				return -EINVAL;
+			}
+			free(filenames[dev]);
+			filenames[dev] = strdup(argv[3]);
+			init_sata(dev);
+			scan_sata(dev);
+			/*
+			 * Scan the partition table if we succeeded in loading
+			 * the new loop file.
+			 */
+			if (sata_dev_desc[dev].lba > 0)
+				init_part(&sata_dev_desc[dev]);
+
+			return 0;
+		}
+		return CMD_RET_USAGE;
+	}
+	return CMD_RET_USAGE;
+}
+
+U_BOOT_CMD(
+	sata_loop, 4, 1, do_loop,
+	"SATA loopback",
+	"info - show info about all loop devices\n"
+	"sata_loop info devnum - show info about loop devnum\n"
+	"sata_loop load devnum file - load file from host FS into loop

devnum" +);

include/configs/sandbox.h +8 -0
index 0220386..a713430 100644
@@ -93,4 +93,12 @@
 
 					"stdout=serial\0" \
 					"stderr=serial\0"
 
+/* SATA loopback device */
+#define CONFIG_CMD_SATA
+#define CONFIG_SATA_LOOP
+#define CONFIG_SYS_SATA_MAX_DEVICE 2
+#define CONFIG_DOS_PARTITION
+#define CONFIG_CMD_FAT
+#define CONFIG_CMD_EXT2
+

#endif

#36 lore raw

PATCH v4 1/2 Loop block device for sandbox

Quoted 20 lines · On Friday 07 of September 2012 11:26:48 Marek Vasut wrote:

Dear Pavel Herrmann,

Quoted 11 lines · On Friday 07 of September 2012 01:29:55 Marek Vasut wrote:
Quoted 10 lines

Dear Pavel Herrmann,

Quoted 3 lines

This driver uses files as block devices, can be used for testing disk operations on sandbox.
A new command "sata_loop" is introduced to load files in runtime.

WARNING: externs should be avoided in .c files
#141: FILE: drivers/block/sata_loopback.c:39:
+extern block_dev_desc_t sata_dev_desc[];

Quoted 6 lines
Quoted 4 lines

total: 0 errors, 1 warnings, 231 lines checked

NOTE: Ignored message types: COMPLEX_MACRO CONSIDER_KSTRTO MINMAX MULTISTATEMENT_MACRO_USE_DO_WHILE

Yes, i know about that, and chose to ignore it.

Quoted 8 lines

Sorry, this is not how it works.

Quoted 3 lines

i will not create a header file for a single line that checkpatch doesnt like (with just a warning), especially when other drivers have such a line in them as well.

So, implement proper accessor for this list? Or export the structure through some sata-related header? How does other do it?

other drivers have the same line that i do, therefore ignore the checkpatch warning, same as i do

see sata_dwc.c, ata_piix.c, fsl_sata.c, sata_sil3114.c

Pavel Herrmann

#37 lore raw

PATCH v4 1/2 Loop block device for sandbox

Dear Pavel Herrmann,

Quoted 27 lines · On Friday 07 of September 2012 11:26:48 Marek Vasut wrote:
Quoted 26 lines

Dear Pavel Herrmann,

Quoted 11 lines · On Friday 07 of September 2012 01:29:55 Marek Vasut wrote:
Quoted 10 lines

Dear Pavel Herrmann,

Quoted 3 lines

This driver uses files as block devices, can be used for testing disk operations on sandbox.
A new command "sata_loop" is introduced to load files in runtime.

WARNING: externs should be avoided in .c files
#141: FILE: drivers/block/sata_loopback.c:39:
+extern block_dev_desc_t sata_dev_desc[];

Quoted 6 lines
Quoted 4 lines

total: 0 errors, 1 warnings, 231 lines checked

NOTE: Ignored message types: COMPLEX_MACRO CONSIDER_KSTRTO MINMAX MULTISTATEMENT_MACRO_USE_DO_WHILE

Yes, i know about that, and chose to ignore it.

Sorry, this is not how it works.

Quoted 3 lines

i will not create a header file for a single line that checkpatch doesnt like (with just a warning), especially when other drivers have such a line in them as well.

Quoted 5 lines
Quoted 2 lines

So, implement proper accessor for this list? Or export the structure through some sata-related header? How does other do it?

other drivers have the same line that i do, therefore ignore the checkpatch warning, same as i do

Oh god damned! This is definitelly not the way to go!

NAK! NAK! NAK!! NAK!!! NAK!!!!! NAK!!!!!!!! ... you get the idea ;-)

Quoted 1 line

see sata_dwc.c, ata_piix.c, fsl_sata.c, sata_sil3114.c

Sad state of codebase, thanks for pointing out the obvious :-( You know, now that you pointed it out, you also know what to do :-)

Besides, you'd have to do it anyway, so let's do it now.

Quoted 1 line

Pavel Herrmann

Best regards,
Marek Vasut

#38 lore raw

PATCH v4 1/2 Loop block device for sandbox

In reply to Pavel Herrmann
Quoted 13 lines · Pavel Herrmann
Quoted 12 lines · On Friday 07 of September 2012 01:29:55 Marek Vasut wrote:

Dear Pavel Herrmann,

Quoted 3 lines

This driver uses files as block devices, can be used for testing disk operations on sandbox.
A new command "sata_loop" is introduced to load files in runtime.

WARNING: externs should be avoided in .c files
#141: FILE: drivers/block/sata_loopback.c:39:
+extern block_dev_desc_t sata_dev_desc[];

total: 0 errors, 1 warnings, 231 lines checked

Quoted 7 lines
Quoted 2 lines

NOTE: Ignored message types: COMPLEX_MACRO CONSIDER_KSTRTO MINMAX MULTISTATEMENT_MACRO_USE_DO_WHILE

Yes, i know about that, and chose to ignore it.
i will not create a header file for a single line that checkpatch doesnt like (with just a warning), especially when other drivers have such a line in them as well.

Please move your extern into <sata.h>, as the starting point before merge. If you could also go and fix:

$ git grep -l sata_dev_desc
common/cmd_sata.c
drivers/block/ata_piix.c
drivers/block/dwc_ahsata.c
drivers/block/dwc_ahsata.h
drivers/block/fsl_sata.c
drivers/block/pata_bfin.c
drivers/block/pata_bfin.h
drivers/block/sata_dwc.c
drivers/block/sata_sil.c
drivers/block/sata_sil.h
drivers/block/sata_sil3114.c

To use <sata.h> (some already do) instead of their own private extern I'd greatly appreciate it.

Signature · 8 lines
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20120913/62ef6192/attachment.pgp>
#39 lore raw

PATCH v4 1/2 Loop block device for sandbox

Hi

Quoted 37 lines · On Thursday 13 September 2012 15:31:39 Tom Rini wrote:
Quoted 13 lines · Pavel Herrmann
Quoted 12 lines · On Friday 07 of September 2012 01:29:55 Marek Vasut wrote:

Dear Pavel Herrmann,

Quoted 3 lines

This driver uses files as block devices, can be used for testing disk operations on sandbox.
A new command "sata_loop" is introduced to load files in runtime.

WARNING: externs should be avoided in .c files
#141: FILE: drivers/block/sata_loopback.c:39:
+extern block_dev_desc_t sata_dev_desc[];

total: 0 errors, 1 warnings, 231 lines checked

Quoted 7 lines
Quoted 2 lines

NOTE: Ignored message types: COMPLEX_MACRO CONSIDER_KSTRTO MINMAX MULTISTATEMENT_MACRO_USE_DO_WHILE

Yes, i know about that, and chose to ignore it.
i will not create a header file for a single line that checkpatch doesnt like (with just a warning), especially when other drivers have such a line in them as well.

Please move your extern into <sata.h>, as the starting point before merge. If you could also go and fix:

$ git grep -l sata_dev_desc
common/cmd_sata.c
drivers/block/ata_piix.c
drivers/block/dwc_ahsata.c
drivers/block/dwc_ahsata.h
drivers/block/fsl_sata.c
drivers/block/pata_bfin.c
drivers/block/pata_bfin.h
drivers/block/sata_dwc.c
drivers/block/sata_sil.c
drivers/block/sata_sil.h
drivers/block/sata_sil3114.c
Quoted 2 lines

To use <sata.h> (some already do) instead of their own private extern I'd greatly appreciate it.

I dont think <sata.h> is the place to put this, as it is a "consumer-facing" header. rather create some common sata header in drivers/block

Pavel Herrmann

#40 lore raw

PATCH v5 1/2 Loop block device for sandbox

In reply to Pavel Herrmann

This driver uses files as block devices, can be used for testing disk operations on sandbox.
A new command "sata_loop" is introduced to load files in runtime.

---
Changes for v5:
use common sata extern header - this requires "[PATCH] Fix checkpatch warnings about externs in *.c" to be merged first
make sure we have valid callbacks before scanning partitions

Changes for v4:
checkpatch fixes
use NULLs instead of ""
extend sata_loop command

Changes for v3:
introduce sata_loop command

Changes for v2:
split sandbox config off into separate patch (2/2) rename file to signify exported API
style fixes
show end of long filenames rather than beginning check for lseek errors to indicate non-regular file

 drivers/block/Makefile        |   1 +
 drivers/block/sata_loopback.c | 213 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 214 insertions(+)
 create mode 100644 drivers/block/sata_loopback.c
drivers/block/Makefile +1 -0
index f1ebdcc..c95651a 100644
@@ -40,6 +40,7 @@ COBJS-$(CONFIG_SATA_SIL) += sata_sil.o
 COBJS-$(CONFIG_IDE_SIL680) += sil680.o
 COBJS-$(CONFIG_SCSI_SYM53C8XX) += sym53c8xx.o
 COBJS-$(CONFIG_SYSTEMACE) += systemace.o
+COBJS-${CONFIG_SATA_LOOP} += sata_loopback.o
 
 COBJS	:= $(COBJS-y)
 SRCS	:= $(COBJS:.o=.c)
drivers/block/sata_loopback.c new file +213 -0

213 lines not on this page · raw message

Signature · 1 line
1.7.12
#41 lore raw

PATCH v6 1/2 Loop block device for sandbox

This driver uses files as block devices, can be used for testing disk operations on sandbox.
A new command "sata_loop" is introduced to load files in runtime.

---
Changes for v6:
sync with new version of "Fix checkpatch warnings about externs in *.c" set all constant disk properties even on not connected drivers

Changes for v5:
use common sata extern header - this requires "[PATCH] Fix checkpatch warnings about externs in *.c" to be merged first
make sure we have valid callbacks before scanning partitions

Changes for v4:
checkpatch fixes
use NULLs instead of ""
extend sata_loop command

Changes for v3:
introduce sata_loop command

Changes for v2:
split sandbox config off into separate patch (2/2) rename file to signify exported API
style fixes
show end of long filenames rather than beginning check for lseek errors to indicate non-regular file

 drivers/block/sata_loopback.c | 209 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 209 insertions(+)
 create mode 100644 drivers/block/sata_loopback.c
drivers/block/sata_loopback.c new file +209 -0
new file mode 100644
index 0000000..b55b270
@@ -0,0 +1,209 @@
+/*
+ * (C) Copyright 2012
+ * Pavel Herrmann <[email protected]>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <part.h>
+#include <ata.h>
+#include <sata.h>
+#include <errno.h>
+#include <os.h>
+#include <command.h>
+#include <malloc.h>
+
+static const char revision[] = "0.0";
+static const char vendor[] = "SATA loopback";
+
+/* this will be auto-initialized to NULLs */
+static char *filenames[CONFIG_SYS_SATA_MAX_DEVICE];
+
+static inline int range_check(int dev)
+{
+	return  (dev < 0) || (dev >= CONFIG_SYS_SATA_MAX_DEVICE);
+}
+
+int init_sata(int dev)
+{
+	block_dev_desc_t *pdev = &sata_dev_desc[dev];
+	int fd, old_fd;
+
+	if (range_check(dev)) {
+		printf("File index %d is out of range.\n", dev);
+		return -EINVAL;
+	}
+
+	if (filenames[dev])
+		fd = os_open(filenames[dev], OS_O_RDWR);
+	else
+		fd = -1;
+
+	old_fd = (long) pdev->priv;
+	/* This is ugly, but saves allocation for 1 int. */
+	pdev->priv = (void *) (long) fd;
+
+	if ((old_fd > 2) || (old_fd < 0))
+		os_close(old_fd);
+
+	return 0;
+}
+
+ulong sata_read(int dev, ulong start, lbaint_t blkcnt, void *buffer)
+{
+	block_dev_desc_t *pdev = &sata_dev_desc[dev];
+	int fd = (long) pdev->priv;
+	lbaint_t start_byte = ATA_SECT_SIZE * start;
+	lbaint_t length_byte = ATA_SECT_SIZE * blkcnt;
+	lbaint_t retval;
+
+	if (os_lseek(fd, start_byte, OS_SEEK_SET) != start_byte)
+		return -1;
+
+	retval = os_read(fd, buffer, length_byte);
+
+	return retval / ATA_SECT_SIZE;
+}
+
+ulong sata_write(int dev, ulong start, lbaint_t blkcnt, const void *buffer)
+{
+	block_dev_desc_t *pdev = &sata_dev_desc[dev];
+	int fd = (long) pdev->priv;
+	lbaint_t start_byte = ATA_SECT_SIZE * start;
+	lbaint_t length_byte = ATA_SECT_SIZE * blkcnt;
+	lbaint_t retval;
+
+	if (os_lseek(fd, start_byte, OS_SEEK_SET) != start_byte)
+		return -1;
+
+	retval = os_write(fd, buffer, length_byte);
+
+	return retval / ATA_SECT_SIZE;
+}
+
+int scan_sata(int dev)
+{
+	block_dev_desc_t *pdev = &sata_dev_desc[dev];
+	int fd = (long) pdev->priv;
+	int namelen;
+	char *filename;
+	lbaint_t bytes = 0;
+
+	if (range_check(dev)) {
+		printf("File index %d is out of range.\n", dev);
+		return -EINVAL;
+	}
+
+	if (filenames[dev])
+		filename = filenames[dev];
+	else
+		filename = "";
+
+	memcpy(pdev->vendor, vendor, sizeof(vendor));
+	memcpy(pdev->revision, revision, sizeof(revision));
+	namelen = strlen(filename);
+
+	if (namelen > 20) {
+		/* take the last 17 chars, prepend them with "..." */
+		memcpy(pdev->product, "...", 3);
+		memcpy(pdev->product+3, filename + (namelen - 17), 17);
+	} else
+		memcpy(pdev->product, filename, namelen);
+
+	pdev->product[20] = 0;
+	pdev->type = DEV_TYPE_HARDDISK;
+	pdev->blksz = ATA_SECT_SIZE;
+	pdev->lun = 0;
+	pdev->block_read = sata_read;
+	pdev->block_write = sata_write;
+
+	bytes = os_lseek(fd, 0, OS_SEEK_END);
+	if (bytes != -1) {
+		pdev->lba = bytes/ATA_SECT_SIZE;
+		printf("SATA loop %d:\nfilename: %s\nsize: %lu\nblock count:"
+			" %lu\n", dev, filename, bytes, pdev->lba);
+	} else {
+		pdev->lba = 0;
+		printf("SATA loop %d:\nfilename: %s\nFAILED TO OPEN\n",
+			 dev, filename);
+	}
+
+	return 0;
+}
+
+
+int do_loop(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	int dev = 0;
+
+	switch (argc) {
+	case 0:
+	case 1:
+		return CMD_RET_USAGE;
+	case 2:
+		if (!strncmp(argv[1], "inf", 3)) {
+			for (dev = 0; dev < CONFIG_SYS_SATA_MAX_DEVICE; dev++)
+				scan_sata(dev);
+			return 0;
+		}
+		return CMD_RET_USAGE;
+	case 3:
+		if (!strncmp(argv[1], "inf", 3)) {
+			dev = simple_strtoul(argv[2], NULL, 10);
+			return scan_sata(dev);
+		}
+		return CMD_RET_USAGE;
+	case 4:
+		if (!strncmp(argv[1], "load", 4)) {
+			dev = simple_strtoul(argv[2], NULL, 10);
+			/*
+			 * init_sata() and scan_sata() do their own range
+			 * check, however we need to explicitly do it here
+			 * as well.
+			 */
+			if (range_check(dev)) {
+				printf("File index %d is out of range.\n", dev);
+				return -EINVAL;
+			}
+			free(filenames[dev]);
+			filenames[dev] = strdup(argv[3]);
+			init_sata(dev);
+			scan_sata(dev);
+			/*
+			 * Scan the partition table if we succeeded in loading
+			 * the new loop file.
+			 */
+			if (sata_dev_desc[dev].lba > 0)
+				init_part(&sata_dev_desc[dev]);
+
+			return 0;
+		}
+		return CMD_RET_USAGE;
+	}
+	return CMD_RET_USAGE;
+}
+
+U_BOOT_CMD(
+	sata_loop, 4, 1, do_loop,
+	"SATA loopback",
+	"info - show info about all loop devices\n"
+	"sata_loop info devnum - show info about loop devnum\n"
+	"sata_loop load devnum file - load file from host FS into loop devnum"
+);
Signature · 1 line
1.7.12
#42 lore raw

PATCH v6 1/2 Loop block device for sandbox

Dear Pavel Herrmann,

Quoted 3 lines

This driver uses files as block devices, can be used for testing disk operations on sandbox.
A new command "sata_loop" is introduced to load files in runtime.

The description might use a little bit of caressing here :)

[...]

Review

Quoted 2 lines
(quoted diff) +2 -0
+	if (os_lseek(fd, start_byte, OS_SEEK_SET) != start_byte)
+		return -1;

Use errno consistently ... so -EINVAL ? Or something else?

Quoted 4 lines
drivers/block/sata_loopback.c new file +4 -0
+	retval = os_read(fd, buffer, length_byte);
+
+	return retval / ATA_SECT_SIZE;
+}

[...]

drivers/block/sata_loopback.c line 174

Quoted 1 line
drivers/block/sata_loopback.c new file +1 -0
+		if (!strncmp(argv[1], "load", 4)) {

if (strncmp())
return CMD_USAGE;

one indent less here ;-)

Quoted 35 lines
drivers/block/sata_loopback.c new file +35 -0
+			dev = simple_strtoul(argv[2], NULL, 10);
+			/*
+			 * init_sata() and scan_sata() do their own range
+			 * check, however we need to explicitly do it here
+			 * as well.
+			 */
+			if (range_check(dev)) {
+				printf("File index %d is out of range.\n", dev);
+				return -EINVAL;
+			}
+			free(filenames[dev]);
+			filenames[dev] = strdup(argv[3]);
+			init_sata(dev);
+			scan_sata(dev);
+			/*
+			 * Scan the partition table if we succeeded in loading
+			 * the new loop file.
+			 */
+			if (sata_dev_desc[dev].lba > 0)
+				init_part(&sata_dev_desc[dev]);
+
+			return 0;
+		}
+		return CMD_RET_USAGE;
+	}
+	return CMD_RET_USAGE;
+}
+
+U_BOOT_CMD(
+	sata_loop, 4, 1, do_loop,
+	"SATA loopback",
+	"info - show info about all loop devices\n"
+	"sata_loop info devnum - show info about loop devnum\n"
+	"sata_loop load devnum file - load file from host FS into loop devnum"
+);