[PATCH] usb: kbd: Also accept keyboards with Interrupt OUT endpoint

2021-02-20 Thread Stefan Brüns
The OUT endpoint can just be ignored as it is not used, just as the
corresponding Set_Report request for IN-only interfaces. E.g. the
Linux gadget hid keyboard also provides an interrupt endpoint.

Also cleanup confusing debug messages like "found set protocol", which
is printed when a keyboard device is found, while the Set_Protocol request
is issued quite some time later.

Signed-off-by: Stefan Brüns 
---
 common/usb_kbd.c | 23 ++-
 1 file changed, 14 insertions(+), 9 deletions(-)

diff --git a/common/usb_kbd.c b/common/usb_kbd.c
index 60c6027e04..afad260d3d 100644
--- a/common/usb_kbd.c
+++ b/common/usb_kbd.c
@@ -443,6 +443,7 @@ static int usb_kbd_probe_dev(struct usb_device *dev, 
unsigned int ifnum)
struct usb_interface *iface;
struct usb_endpoint_descriptor *ep;
struct usb_kbd_pdata *data;
+   int epNum;
 
if (dev->descriptor.bNumConfigurations != 1)
return 0;
@@ -458,19 +459,21 @@ static int usb_kbd_probe_dev(struct usb_device *dev, 
unsigned int ifnum)
if (iface->desc.bInterfaceProtocol != USB_PROT_HID_KEYBOARD)
return 0;
 
-   if (iface->desc.bNumEndpoints != 1)
-   return 0;
+   for (epNum = 0; epNum < iface->desc.bNumEndpoints; epNum++) {
+   ep = >ep_desc[epNum];
 
-   ep = >ep_desc[0];
+   /* Check if endpoint is interrupt IN endpoint */
+   if ((ep->bmAttributes & 3) != 3)
+   continue;
 
-   /* Check if endpoint 1 is interrupt endpoint */
-   if (!(ep->bEndpointAddress & 0x80))
-   return 0;
+   if (ep->bEndpointAddress & 0x80)
+   break;
+   }
 
-   if ((ep->bmAttributes & 3) != 3)
+   if (epNum == iface->desc.bNumEndpoints)
return 0;
 
-   debug("USB KBD: found set protocol...\n");
+   debug("USB KBD: found interrupt EP: 0x%x\n", ep->bEndpointAddress);
 
data = malloc(sizeof(struct usb_kbd_pdata));
if (!data) {
@@ -498,13 +501,15 @@ static int usb_kbd_probe_dev(struct usb_device *dev, 
unsigned int ifnum)
data->last_report = -1;
 
/* We found a USB Keyboard, install it. */
+   debug("USB KBD: set boot protocol\n");
usb_set_protocol(dev, iface->desc.bInterfaceNumber, 0);
 
-   debug("USB KBD: found set idle...\n");
 #if !defined(CONFIG_SYS_USB_EVENT_POLL_VIA_CONTROL_EP) && \
 !defined(CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE)
+   debug("USB KBD: set idle interval...\n");
usb_set_idle(dev, iface->desc.bInterfaceNumber, REPEAT_RATE / 4, 0);
 #else
+   debug("USB KBD: set idle interval=0...\n");
usb_set_idle(dev, iface->desc.bInterfaceNumber, 0, 0);
 #endif
 
-- 
2.30.1



[U-Boot] [PATCH] patman: Unquote output from get_maintainer.pl

2018-01-01 Thread Stefan Brüns
get_maintainer.pl quotes names which it considers unsafe, i.e. anything
containing [^a-zA-Z0-9_ \-]. This confuses patman, it will duplicate
addresses which are also in Series-to/cc. Strip the quotes.

Signed-off-by: Stefan Brüns <stefan.bru...@rwth-aachen.de>

---

 tools/patman/get_maintainer.py | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/tools/patman/get_maintainer.py b/tools/patman/get_maintainer.py
index 2deb5db6ec..22b091808a 100644
--- a/tools/patman/get_maintainer.py
+++ b/tools/patman/get_maintainer.py
@@ -44,4 +44,5 @@ def GetMaintainer(fname, verbose=False):
 return []
 
 stdout = command.Output(get_maintainer, '--norolestats', fname)
-return stdout.splitlines()
+lines = stdout.splitlines()
+return [ x.replace('"', '') for x in lines ]
-- 
2.15.1

___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot


Re: [U-Boot] [linux-sunxi] Re: [PATCH 12/16] configs: sun50i: enable ums on bananapi-m64

2017-12-12 Thread Stefan Brüns
On Wednesday, December 13, 2017 2:36:26 AM CET Icenowy Zheng wrote:
> 在 2017年12月12日星期二 CST 下午4:12:13,Maxime Ripard 写道:
> 
> > Hi,
> > 
> > On Tue, Dec 12, 2017 at 12:28:27PM +0530, Jagan Teki wrote:
> > > This patch enable ums through CMD_USB_MASS_STORAGE.
> > > 
> > > Signed-off-by: Jagan Teki <ja...@amarulasolutions.com>
> > > ---
> > > 
> > >  configs/bananapi_m64_defconfig | 1 +
> > >  1 file changed, 1 insertion(+)
> > > 
> > > diff --git a/configs/bananapi_m64_defconfig
> > > b/configs/bananapi_m64_defconfig index 55feafe..d4aade5 100644
> > > --- a/configs/bananapi_m64_defconfig
> > > +++ b/configs/bananapi_m64_defconfig
> > > @@ -11,6 +11,7 @@ CONFIG_DEFAULT_DEVICE_TREE="sun50i-a64-bananapi-m64"
> > > 
> > >  CONFIG_SPL=y
> > >  # CONFIG_CMD_FLASH is not set
> > >  # CONFIG_CMD_FPGA is not set
> > > 
> > > +CONFIG_CMD_USB_MASS_STORAGE=y
> > 
> > How does that work with the current over-size issue we have on the
> > A64?
> > 
> > And I'd also like to keep the way we did things for several years now,
> > which is to *not* have board-specific options selected besides the
> > hardware-related ones.
> > 
> > If you want to enable a general feature, do it for all the boards so
> > that our users will have a consistent experience across boards, and we
> > will not have to always chase all the defconfigs to provide it.
> 
> I think there's a problem on A64 -- the Pine series are all designed to be
> host-only, and it's the most popular A64 board series.

No, it just means the *initial* role of the Pine will be Host, but the roles 
can be swapped using HNP (Host Negotiation Protocol) afterwards, which is pure 
software.

Regards,

Stefan

-- 
Stefan Brüns  /  Bergstraße 21  /  52062 Aachen
home: +49 241 53809034 mobile: +49 151 50412019

signature.asc
Description: This is a digitally signed message part.
___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot


[U-Boot] [PATCH v1] Document padding between GPT header and partition entries

2017-10-17 Thread Stefan Brüns
Commit 02e43537b322 ("part_efi: support padding between the GPT
header and partition entries") added support for deviating from
the typical GPT layout.

Explicitly state deviations are allowed/possible, and mention when
(SoC SPL) and when not (compatibility) deviations are useful. Also
mention support for non-standard layouts in gdisk 1.0.3.

Signed-off-by: Stefan Brüns <stefan.bru...@rwth-aachen.de>

---

 doc/README.gpt | 33 +
 1 file changed, 29 insertions(+), 4 deletions(-)

diff --git a/doc/README.gpt b/doc/README.gpt
index d3db8bce1c..7134f3b3cf 100644
--- a/doc/README.gpt
+++ b/doc/README.gpt
@@ -44,8 +44,8 @@ uuid command line tool).
 GPT brief explanation:
 ==
 
-   Layout:
-   ---
+   Default layout:
+   ---
 
--
LBA 0  |Protective MBR   |
@@ -82,7 +82,29 @@ For a legacy reasons, GPT's LBA 0 sector has a MBR 
structure. It is called
 Its first partition entry ID has 0xEE value, and disk software, which is not
 handling the GPT sees it as a storage device without free space.
 
-It is possible to define 128 linearly placed partition entries.
+By default, the first partition entry of the primary GPT is stored in LBA 2,
+although this is not explicitly mandated by the UEFI specification. The
+start LBAs of the partition entries are given in the corresponding GPT
+headers (Primary/Backup) (offset 72 bytes).
+
+The UEFI specification mandates at least 128 contigously stored partition
+entries, the number is specified in the GPT headers (offset 80).
+
+As several SoCs require the SPL to be located at a fixed position, often
+below LBA 34 (17 kByte for 512 byte blocks), it is possible to deviate
+from the standard layout:
+
+1. Lower the number of partition entries. This violates the UEFI/GPT
+   specification, but usually works.
+2. Insert a gap between Primary GPT Header and partition entries. This
+   is in line with the specification, but may cause problems with tools
+   or operating systems hardcoding the partition entries LBA to 2.
+
+There is limited support for both variants in U-Boot - reading is fully
+supported, while the "gpt write" command always creates a GPT with 128
+entries. A gap is created when CONFIG_EFI_PARTITION_ENTRIES_OFF is set
+or when the device tree "/config" node contains a property
+"u-boot,efi-partition-entries-offset".
 
 "LBA -1" means the last addressable block (in the mmc subsystem:
 "dev_desc->lba - 1")
@@ -103,7 +125,7 @@ Offset  SizeDescription
LBA + 1)
 48  8 B Last usable LBA (secondary partition table first LBA - 1)
 56  16 BDisk GUID (also referred as UUID on UNIXes)
-72  8 B Partition entries starting LBA (always 2 in primary copy)
+72  8 B Partition entries starting LBA (usually 2 in primary copy)
 80  4 B Number of partition entries
 84  4 B Size of a partition entry (usually 128)
 88  4 B CRC32 of partition array
@@ -283,6 +305,9 @@ Two programs, namely: 'gdisk' and 'parted' are recommended 
to work with GPT
 recovery. Both are able to handle GUID partitions.
 Please, pay attention at -l switch for parted.
 
+'gdisk' as of version 1.0.3 is able to create tables with a number of partition
+entries different to 128, and insert padding after the GPT header.
+
 "uuid" program is recommended to generate UUID string. Moreover it can decode
 (-d switch) passed in UUID string. It can be used to generate partitions UUID
 passed to u-boot environment variables.
-- 
2.14.2

___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot


[U-Boot] [PATCH] fs/ext4: Initialize group descriptor size for revision level 0 filesystems

2016-12-26 Thread Stefan Brüns
genext2fs creates revision level 0 filesystems, which are not readable
by u-boot due to the initialized group descriptor size field.
f798b1dda1c5de818b806189e523d1b75db7e72d

Reported-by: Kever Yang <kever.y...@rock-chips.com>
Reported-by: frostyby...@protonmail.com
Signed-off-by: Stefan Brüns <stefan.bru...@rwth-aachen.de>
---
 fs/ext4/ext4_common.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/fs/ext4/ext4_common.c b/fs/ext4/ext4_common.c
index bfebe7e379..621c61e5c7 100644
--- a/fs/ext4/ext4_common.c
+++ b/fs/ext4/ext4_common.c
@@ -2334,6 +2334,7 @@ int ext4fs_mount(unsigned part_length)
 
if (le32_to_cpu(data->sblock.revision_level) == 0) {
fs->inodesz = 128;
+   fs->gdsize = 32;
} else {
debug("EXT4 features COMPAT: %08x INCOMPAT: %08x RO_COMPAT: 
%08x\n",
  __le32_to_cpu(data->sblock.feature_compatibility),
-- 
2.11.0

___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


[U-Boot] [PATCH] fs/fat: simplify get_fatent for FAT12

2016-12-16 Thread Stefan Brüns
From: Stefan Brüns <stefan.bru...@rwth-aachen.de>

Instead of shuffling bits from two adjacent 16 bit words, use one 16 bit
word with the appropriate byte offset in the buffer.

Signed-off-by: Stefan Brüns <stefan.bru...@rwth-aachen.de>
---
 fs/fat/fat.c | 34 +-
 1 file changed, 5 insertions(+), 29 deletions(-)

diff --git a/fs/fat/fat.c b/fs/fat/fat.c
index 73c3dd7f85..fe899d0442 100644
--- a/fs/fat/fat.c
+++ b/fs/fat/fat.c
@@ -181,7 +181,6 @@ static __u32 get_fatent(fsdata *mydata, __u32 entry)
__u32 bufnum;
__u32 off16, offset;
__u32 ret = 0x00;
-   __u16 val1, val2;
 
if (CHECK_CLUST(entry, mydata->fatsize)) {
printf("Error: Invalid FAT entry: 0x%08x\n", entry);
@@ -243,35 +242,12 @@ static __u32 get_fatent(fsdata *mydata, __u32 entry)
ret = FAT2CPU16(((__u16 *) mydata->fatbuf)[offset]);
break;
case 12:
-   off16 = (offset * 3) / 4;
+   off16 = (offset * 3) / 2;
+   ret = FAT2CPU16(*(__u16 *)(mydata->fatbuf + off16));
 
-   switch (offset & 0x3) {
-   case 0:
-   ret = FAT2CPU16(((__u16 *) mydata->fatbuf)[off16]);
-   ret &= 0xfff;
-   break;
-   case 1:
-   val1 = FAT2CPU16(((__u16 *)mydata->fatbuf)[off16]);
-   val1 &= 0xf000;
-   val2 = FAT2CPU16(((__u16 *)mydata->fatbuf)[off16 + 1]);
-   val2 &= 0x00ff;
-   ret = (val2 << 4) | (val1 >> 12);
-   break;
-   case 2:
-   val1 = FAT2CPU16(((__u16 *)mydata->fatbuf)[off16]);
-   val1 &= 0xff00;
-   val2 = FAT2CPU16(((__u16 *)mydata->fatbuf)[off16 + 1]);
-   val2 &= 0x000f;
-   ret = (val2 << 8) | (val1 >> 8);
-   break;
-   case 3:
-   ret = FAT2CPU16(((__u16 *)mydata->fatbuf)[off16]);
-   ret = (ret & 0xfff0) >> 4;
-   break;
-   default:
-   break;
-   }
-   break;
+   if (offset & 0x1)
+   ret >>= 4;
+   ret &= 0xfff;
}
debug("FAT%d: ret: 0x%08x, entry: 0x%08x, offset: 0x%04x\n",
   mydata->fatsize, ret, entry, offset);
-- 
2.11.0

___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


[U-Boot] [PATCH v2 2/2] fs/fat: merge readwrite get_fatent_value() with readonly get_fatent()

2016-12-16 Thread Stefan Brüns
get_fatent_value(...) flushes changed FAT entries to disk when fetching
the next FAT blocks, in every other aspect it is identical to
get_fatent(...).

Provide a stub implementation for flush_dirty_fat_buffer if
CONFIG_FAT_WRITE is not set. Calling flush_dirty_fat_buffer during read
only operation is fine as it checks if any buffers needs flushing.

Signed-off-by: Stefan Brüns <stefan.bru...@rwth-aachen.de>
Reviewed-by: Benoît Thébaudeau <benoit.thebaudeau@gmail.com>
---
 fs/fat/fat.c   |  25 ++--
 fs/fat/fat_write.c | 118 +++--
 2 files changed, 27 insertions(+), 116 deletions(-)

diff --git a/fs/fat/fat.c b/fs/fat/fat.c
index 6319581406..73c3dd7f85 100644
--- a/fs/fat/fat.c
+++ b/fs/fat/fat.c
@@ -162,6 +162,16 @@ static void get_name(dir_entry *dirent, char *s_name)
downcase(s_name);
 }
 
+static int flush_dirty_fat_buffer(fsdata *mydata);
+#if !defined(CONFIG_FAT_WRITE)
+/* Stub for read only operation */
+int flush_dirty_fat_buffer(fsdata *mydata)
+{
+   (void)(mydata);
+   return 0;
+}
+#endif
+
 /*
  * Get the entry at index 'entry' in a FAT (12/16/32) table.
  * On failure 0x00 is returned.
@@ -173,6 +183,11 @@ static __u32 get_fatent(fsdata *mydata, __u32 entry)
__u32 ret = 0x00;
__u16 val1, val2;
 
+   if (CHECK_CLUST(entry, mydata->fatsize)) {
+   printf("Error: Invalid FAT entry: 0x%08x\n", entry);
+   return ret;
+   }
+
switch (mydata->fatsize) {
case 32:
bufnum = entry / FAT32BUFSIZE;
@@ -192,7 +207,7 @@ static __u32 get_fatent(fsdata *mydata, __u32 entry)
return ret;
}
 
-   debug("FAT%d: entry: 0x%04x = %d, offset: 0x%04x = %d\n",
+   debug("FAT%d: entry: 0x%08x = %d, offset: 0x%04x = %d\n",
   mydata->fatsize, entry, entry, offset, offset);
 
/* Read a new block of FAT entries into the cache. */
@@ -208,6 +223,10 @@ static __u32 get_fatent(fsdata *mydata, __u32 entry)
 
startblock += mydata->fat_sect; /* Offset from start of disk */
 
+   /* Write back the fatbuf to the disk */
+   if (flush_dirty_fat_buffer(mydata) < 0)
+   return -1;
+
if (disk_read(startblock, getsize, bufptr) < 0) {
debug("Error reading FAT blocks\n");
return ret;
@@ -254,8 +273,8 @@ static __u32 get_fatent(fsdata *mydata, __u32 entry)
}
break;
}
-   debug("FAT%d: ret: %08x, offset: %04x\n",
-  mydata->fatsize, ret, offset);
+   debug("FAT%d: ret: 0x%08x, entry: 0x%08x, offset: 0x%04x\n",
+  mydata->fatsize, ret, entry, offset);
 
return ret;
 }
diff --git a/fs/fat/fat_write.c b/fs/fat/fat_write.c
index 0be60ecd99..c05fc7f099 100644
--- a/fs/fat/fat_write.c
+++ b/fs/fat/fat_write.c
@@ -143,114 +143,6 @@ static int flush_dirty_fat_buffer(fsdata *mydata)
 }
 
 /*
- * Get the entry at index 'entry' in a FAT (12/16/32) table.
- * On failure 0x00 is returned.
- * When bufnum is changed, write back the previous fatbuf to the disk.
- */
-static __u32 get_fatent_value(fsdata *mydata, __u32 entry)
-{
-   __u32 bufnum;
-   __u32 off16, offset;
-   __u32 ret = 0x00;
-   __u16 val1, val2;
-
-   if (CHECK_CLUST(entry, mydata->fatsize)) {
-   printf("Error: Invalid FAT entry: 0x%08x\n", entry);
-   return ret;
-   }
-
-   switch (mydata->fatsize) {
-   case 32:
-   bufnum = entry / FAT32BUFSIZE;
-   offset = entry - bufnum * FAT32BUFSIZE;
-   break;
-   case 16:
-   bufnum = entry / FAT16BUFSIZE;
-   offset = entry - bufnum * FAT16BUFSIZE;
-   break;
-   case 12:
-   bufnum = entry / FAT12BUFSIZE;
-   offset = entry - bufnum * FAT12BUFSIZE;
-   break;
-
-   default:
-   /* Unsupported FAT size */
-   return ret;
-   }
-
-   debug("FAT%d: entry: 0x%04x = %d, offset: 0x%04x = %d\n",
-  mydata->fatsize, entry, entry, offset, offset);
-
-   /* Read a new block of FAT entries into the cache. */
-   if (bufnum != mydata->fatbufnum) {
-   int getsize = FATBUFBLOCKS;
-   __u8 *bufptr = mydata->fatbuf;
-   __u32 fatlength = mydata->fatlength;
-   __u32 startblock = bufnum * FATBUFBLOCKS;
-
-   /* Cap length if fatlength is not a multiple of FATBUFBLOCKS */
-   if (startblock + getsize > fatlength)
-   getsize = fatlength - startblock;
-
-   startblock += mydata->fat_sect; /* Offset from start of disk */
-
-   /* Write back the fatbuf to the disk */
- 

[U-Boot] [PATCH v2 1/2] fs/fat: Avoid corruption of sectors following the FAT

2016-12-16 Thread Stefan Brüns
The FAT is read/flushed in segments of 6 (FATBUFBLOCKS) disk sectors. The
last segment may be less than 6 sectors, cap the length.

Signed-off-by: Stefan Brüns <stefan.bru...@rwth-aachen.de>
Reviewed-by: Benoît Thébaudeau <benoit.thebaudeau@gmail.com>
---
 fs/fat/fat.c   |  1 +
 fs/fat/fat_write.c | 22 --
 2 files changed, 13 insertions(+), 10 deletions(-)

diff --git a/fs/fat/fat.c b/fs/fat/fat.c
index df9f2b5656..6319581406 100644
--- a/fs/fat/fat.c
+++ b/fs/fat/fat.c
@@ -202,6 +202,7 @@ static __u32 get_fatent(fsdata *mydata, __u32 entry)
__u32 fatlength = mydata->fatlength;
__u32 startblock = bufnum * FATBUFBLOCKS;
 
+   /* Cap length if fatlength is not a multiple of FATBUFBLOCKS */
if (startblock + getsize > fatlength)
getsize = fatlength - startblock;
 
diff --git a/fs/fat/fat_write.c b/fs/fat/fat_write.c
index 40a3860e47..0be60ecd99 100644
--- a/fs/fat/fat_write.c
+++ b/fs/fat/fat_write.c
@@ -117,10 +117,11 @@ static int flush_dirty_fat_buffer(fsdata *mydata)
if ((!mydata->fat_dirty) || (mydata->fatbufnum == -1))
return 0;
 
-   startblock += mydata->fat_sect;
+   /* Cap length if fatlength is not a multiple of FATBUFBLOCKS */
+   if (startblock + getsize > fatlength)
+   getsize = fatlength - startblock;
 
-   if (getsize > fatlength)
-   getsize = fatlength;
+   startblock += mydata->fat_sect;
 
/* Write FAT buf */
if (disk_write(startblock, getsize, bufptr) < 0) {
@@ -187,8 +188,9 @@ static __u32 get_fatent_value(fsdata *mydata, __u32 entry)
__u32 fatlength = mydata->fatlength;
__u32 startblock = bufnum * FATBUFBLOCKS;
 
-   if (getsize > fatlength)
-   getsize = fatlength;
+   /* Cap length if fatlength is not a multiple of FATBUFBLOCKS */
+   if (startblock + getsize > fatlength)
+   getsize = fatlength - startblock;
 
startblock += mydata->fat_sect; /* Offset from start of disk */
 
@@ -494,15 +496,15 @@ static int set_fatent_value(fsdata *mydata, __u32 entry, 
__u32 entry_value)
__u32 fatlength = mydata->fatlength;
__u32 startblock = bufnum * FATBUFBLOCKS;
 
-   fatlength *= mydata->sect_size;
-   startblock += mydata->fat_sect;
-
-   if (getsize > fatlength)
-   getsize = fatlength;
+   /* Cap length if fatlength is not a multiple of FATBUFBLOCKS */
+   if (startblock + getsize > fatlength)
+   getsize = fatlength - startblock;
 
if (flush_dirty_fat_buffer(mydata) < 0)
return -1;
 
+   startblock += mydata->fat_sect;
+
if (disk_read(startblock, getsize, bufptr) < 0) {
debug("Error reading FAT blocks\n");
return -1;
-- 
2.11.0

___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


[U-Boot] [PATCH v2 0/2] fs/fat: more bugfixes, cleanups

2016-12-16 Thread Stefan Brüns
Fix a possible filesystem corruption if the FS is almost full, and
remove some duplicate code.

Stefan Brüns (2):
  fs/fat: Avoid corruption of sectors following the FAT
  fs/fat: merge readwrite get_fatent_value() with readonly get_fatent()

 fs/fat/fat.c   |  26 +--
 fs/fat/fat_write.c | 134 ++---
 2 files changed, 37 insertions(+), 123 deletions(-)

v2: fixed author tag encoding
use consistent debut output formatting
added rb: Benoît Thébaudeau <benoit.thebaudeau@gmail.com>
-- 
2.11.0

___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


[U-Boot] [PATCH v3 1/2] test/py: Pass u_boot_log instead of console for run_and_log

2016-12-11 Thread Stefan Brüns
From: Stefan Brüns <stefan.bru...@rwth-aachen.de>

The runner actually has no console dependency, only on the log provided
by the console.

Signed-off-by: Stefan Brüns <stefan.bru...@rwth-aachen.de>
---
Alternate approach to the previous patch, always pass the logfile, change
all callers accordingly.

 test/py/tests/test_dfu.py   |  2 +-
 test/py/tests/test_ums.py   | 10 +-
 test/py/tests/test_vboot.py | 18 +-
 test/py/u_boot_utils.py | 12 ++--
 4 files changed, 21 insertions(+), 21 deletions(-)

diff --git a/test/py/tests/test_dfu.py b/test/py/tests/test_dfu.py
index 585e6b29d7..b4f9a32abc 100644
--- a/test/py/tests/test_dfu.py
+++ b/test/py/tests/test_dfu.py
@@ -206,7 +206,7 @@ def test_dfu(u_boot_console, env__usb_dev_port, 
env__dfu_config):
 cmd = ['dfu-util', '-a', alt_setting, up_dn_load_arg, fn]
 if 'host_usb_port_path' in env__usb_dev_port:
 cmd += ['-p', env__usb_dev_port['host_usb_port_path']]
-u_boot_utils.run_and_log(u_boot_console, cmd)
+u_boot_utils.run_and_log(u_boot_console.log, cmd)
 u_boot_console.wait_for('Ctrl+C to exit ...')
 
 def dfu_write(alt_setting, fn):
diff --git a/test/py/tests/test_ums.py b/test/py/tests/test_ums.py
index 8c3ee2b053..54c47b0aee 100644
--- a/test/py/tests/test_ums.py
+++ b/test/py/tests/test_ums.py
@@ -156,7 +156,7 @@ def test_ums(u_boot_console, env__usb_dev_port, 
env__block_devs):
 
 u_boot_console.log.action('Mounting exported UMS device')
 cmd = ('/bin/mount', host_ums_part_node)
-u_boot_utils.run_and_log(u_boot_console, cmd)
+u_boot_utils.run_and_log(u_boot_console.log, cmd)
 
 def umount(ignore_errors):
 """Unmount the block device that U-Boot exports.
@@ -173,7 +173,7 @@ def test_ums(u_boot_console, env__usb_dev_port, 
env__block_devs):
 
 u_boot_console.log.action('Unmounting UMS device')
 cmd = ('/bin/umount', host_ums_part_node)
-u_boot_utils.run_and_log(u_boot_console, cmd, ignore_errors)
+u_boot_utils.run_and_log(u_boot_console.log, cmd, ignore_errors)
 
 def stop_ums(ignore_errors):
 """Stop U-Boot's ums shell command from executing.
@@ -207,11 +207,11 @@ def test_ums(u_boot_console, env__usb_dev_port, 
env__block_devs):
 mount()
 u_boot_console.log.action('Writing test file via UMS')
 cmd = ('rm', '-f', mounted_test_fn)
-u_boot_utils.run_and_log(u_boot_console, cmd)
+u_boot_utils.run_and_log(u_boot_console.log, cmd)
 if os.path.exists(mounted_test_fn):
 raise Exception('Could not rm target UMS test file')
 cmd = ('cp', test_f.abs_fn, mounted_test_fn)
-u_boot_utils.run_and_log(u_boot_console, cmd)
+u_boot_utils.run_and_log(u_boot_console.log, cmd)
 ignore_cleanup_errors = False
 finally:
 umount(ignore_errors=ignore_cleanup_errors)
@@ -226,7 +226,7 @@ def test_ums(u_boot_console, env__usb_dev_port, 
env__block_devs):
 u_boot_console.log.action('Reading test file back via UMS')
 read_back_hash = u_boot_utils.md5sum_file(mounted_test_fn)
 cmd = ('rm', '-f', mounted_test_fn)
-u_boot_utils.run_and_log(u_boot_console, cmd)
+u_boot_utils.run_and_log(u_boot_console.log, cmd)
 ignore_cleanup_errors = False
 finally:
 umount(ignore_errors=ignore_cleanup_errors)
diff --git a/test/py/tests/test_vboot.py b/test/py/tests/test_vboot.py
index 6e62820743..0f893f1e91 100644
--- a/test/py/tests/test_vboot.py
+++ b/test/py/tests/test_vboot.py
@@ -50,7 +50,7 @@ def test_vboot(u_boot_console):
 dts: Device tree file to compile.
 """
 dtb = dts.replace('.dts', '.dtb')
-util.run_and_log(cons, 'dtc %s %s%s -O dtb '
+util.run_and_log(cons.log, 'dtc %s %s%s -O dtb '
  '-o %s%s' % (dtc_args, datadir, dts, tmpdir, dtb))
 
 def run_bootm(sha_algo, test_type, expect_string, boots):
@@ -85,7 +85,7 @@ def test_vboot(u_boot_console):
 Args:
 its: Filename containing .its source.
 """
-util.run_and_log(cons, [mkimage, '-D', dtc_args, '-f',
+util.run_and_log(cons.log, [mkimage, '-D', dtc_args, '-f',
 '%s%s' % (datadir, its), fit])
 
 def sign_fit(sha_algo):
@@ -99,7 +99,7 @@ def test_vboot(u_boot_console):
 use.
 """
 cons.log.action('%s: Sign images' % sha_algo)
-util.run_and_log(cons, [mkimage, '-F', '-k', tmpdir, '-K', dtb,
+util.run_and_log(cons.log, [mkimage, '-F', '-k', tmpdir, '-K', dtb,
 '-r', fit])
 
 def test_with_algo(sha_algo):
@@ -140,23 +140,23 @@ def test_vboot(u_boot_console):
 
 cons.log.action('%s: Check signed

[U-Boot] [PATCH 0/2] fs/fat: more bugfixes, cleanups

2016-12-10 Thread Stefan Brüns
Fix a possible filesystem corruption if the FS is almost full, and
remove some duplicate code.

Stefan Brüns (1):
  fs/fat: Avoid corruption of sectors following the FAT

Stefan Brüns (1):
  fs/fat: merge readwrite get_fatent_value() with readonly get_fatent()

 fs/fat/fat.c   |  20 
 fs/fat/fat_write.c | 134 ++---
 2 files changed, 34 insertions(+), 120 deletions(-)

-- 
2.11.0

___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


[U-Boot] [PATCH 2/2] fs/fat: merge readwrite get_fatent_value() with readonly get_fatent()

2016-12-10 Thread Stefan Brüns
get_fatent_value(...) flushes changed FAT entries to disk when fetching
the next FAT blocks, in every other aspect it is identical to
get_fatent(...).

Provide a stub implementation for flush_dirty_fat_buffer if
CONFIG_FAT_WRITE is not set. Calling flush_dirty_fat_buffer during read
only operation is fine as it checks if any buffers needs flushing.

Signed-off-by: Stefan Brüns <stefan.bru...@rwth-aachen.de>
---
 fs/fat/fat.c   |  19 +
 fs/fat/fat_write.c | 118 +++--
 2 files changed, 24 insertions(+), 113 deletions(-)

diff --git a/fs/fat/fat.c b/fs/fat/fat.c
index 6319581406..554e811587 100644
--- a/fs/fat/fat.c
+++ b/fs/fat/fat.c
@@ -162,6 +162,16 @@ static void get_name(dir_entry *dirent, char *s_name)
downcase(s_name);
 }
 
+static int flush_dirty_fat_buffer(fsdata *mydata);
+#if !defined(CONFIG_FAT_WRITE)
+/* Stub for read only operation */
+int flush_dirty_fat_buffer(fsdata *mydata)
+{
+   (void)(mydata);
+   return 0;
+}
+#endif
+
 /*
  * Get the entry at index 'entry' in a FAT (12/16/32) table.
  * On failure 0x00 is returned.
@@ -173,6 +183,11 @@ static __u32 get_fatent(fsdata *mydata, __u32 entry)
__u32 ret = 0x00;
__u16 val1, val2;
 
+   if (CHECK_CLUST(entry, mydata->fatsize)) {
+   printf("Error: Invalid FAT entry: 0x%08x\n", entry);
+   return ret;
+   }
+
switch (mydata->fatsize) {
case 32:
bufnum = entry / FAT32BUFSIZE;
@@ -208,6 +223,10 @@ static __u32 get_fatent(fsdata *mydata, __u32 entry)
 
startblock += mydata->fat_sect; /* Offset from start of disk */
 
+   /* Write back the fatbuf to the disk */
+   if (flush_dirty_fat_buffer(mydata) < 0)
+   return -1;
+
if (disk_read(startblock, getsize, bufptr) < 0) {
debug("Error reading FAT blocks\n");
return ret;
diff --git a/fs/fat/fat_write.c b/fs/fat/fat_write.c
index 0be60ecd99..c05fc7f099 100644
--- a/fs/fat/fat_write.c
+++ b/fs/fat/fat_write.c
@@ -143,114 +143,6 @@ static int flush_dirty_fat_buffer(fsdata *mydata)
 }
 
 /*
- * Get the entry at index 'entry' in a FAT (12/16/32) table.
- * On failure 0x00 is returned.
- * When bufnum is changed, write back the previous fatbuf to the disk.
- */
-static __u32 get_fatent_value(fsdata *mydata, __u32 entry)
-{
-   __u32 bufnum;
-   __u32 off16, offset;
-   __u32 ret = 0x00;
-   __u16 val1, val2;
-
-   if (CHECK_CLUST(entry, mydata->fatsize)) {
-   printf("Error: Invalid FAT entry: 0x%08x\n", entry);
-   return ret;
-   }
-
-   switch (mydata->fatsize) {
-   case 32:
-   bufnum = entry / FAT32BUFSIZE;
-   offset = entry - bufnum * FAT32BUFSIZE;
-   break;
-   case 16:
-   bufnum = entry / FAT16BUFSIZE;
-   offset = entry - bufnum * FAT16BUFSIZE;
-   break;
-   case 12:
-   bufnum = entry / FAT12BUFSIZE;
-   offset = entry - bufnum * FAT12BUFSIZE;
-   break;
-
-   default:
-   /* Unsupported FAT size */
-   return ret;
-   }
-
-   debug("FAT%d: entry: 0x%04x = %d, offset: 0x%04x = %d\n",
-  mydata->fatsize, entry, entry, offset, offset);
-
-   /* Read a new block of FAT entries into the cache. */
-   if (bufnum != mydata->fatbufnum) {
-   int getsize = FATBUFBLOCKS;
-   __u8 *bufptr = mydata->fatbuf;
-   __u32 fatlength = mydata->fatlength;
-   __u32 startblock = bufnum * FATBUFBLOCKS;
-
-   /* Cap length if fatlength is not a multiple of FATBUFBLOCKS */
-   if (startblock + getsize > fatlength)
-   getsize = fatlength - startblock;
-
-   startblock += mydata->fat_sect; /* Offset from start of disk */
-
-   /* Write back the fatbuf to the disk */
-   if (flush_dirty_fat_buffer(mydata) < 0)
-   return -1;
-
-   if (disk_read(startblock, getsize, bufptr) < 0) {
-   debug("Error reading FAT blocks\n");
-   return ret;
-   }
-   mydata->fatbufnum = bufnum;
-   }
-
-   /* Get the actual entry from the table */
-   switch (mydata->fatsize) {
-   case 32:
-   ret = FAT2CPU32(((__u32 *) mydata->fatbuf)[offset]);
-   break;
-   case 16:
-   ret = FAT2CPU16(((__u16 *) mydata->fatbuf)[offset]);
-   break;
-   case 12:
-   off16 = (offset * 3) / 4;
-
-   switch (offset & 0x3) {
-   case 0:
-   ret = FAT2CPU16(((__u16 *) mydata->fatbuf)[off16]);
-

[U-Boot] [PATCH 1/2] fs/fat: Avoid corruption of sectors following the FAT

2016-12-10 Thread Stefan Brüns
From: Stefan Brüns <stefan.bru...@rwth-aachen.de>

The FAT is read/flushed in segments of 6 (FATBUFBLOCKS) disk sectors. The
last segment may be less than 6 sectors, cap the length.

Signed-off-by: Stefan Brüns <stefan.bru...@rwth-aachen.de>
---
 fs/fat/fat.c   |  1 +
 fs/fat/fat_write.c | 22 --
 2 files changed, 13 insertions(+), 10 deletions(-)

diff --git a/fs/fat/fat.c b/fs/fat/fat.c
index df9f2b5656..6319581406 100644
--- a/fs/fat/fat.c
+++ b/fs/fat/fat.c
@@ -202,6 +202,7 @@ static __u32 get_fatent(fsdata *mydata, __u32 entry)
__u32 fatlength = mydata->fatlength;
__u32 startblock = bufnum * FATBUFBLOCKS;
 
+   /* Cap length if fatlength is not a multiple of FATBUFBLOCKS */
if (startblock + getsize > fatlength)
getsize = fatlength - startblock;
 
diff --git a/fs/fat/fat_write.c b/fs/fat/fat_write.c
index 40a3860e47..0be60ecd99 100644
--- a/fs/fat/fat_write.c
+++ b/fs/fat/fat_write.c
@@ -117,10 +117,11 @@ static int flush_dirty_fat_buffer(fsdata *mydata)
if ((!mydata->fat_dirty) || (mydata->fatbufnum == -1))
return 0;
 
-   startblock += mydata->fat_sect;
+   /* Cap length if fatlength is not a multiple of FATBUFBLOCKS */
+   if (startblock + getsize > fatlength)
+   getsize = fatlength - startblock;
 
-   if (getsize > fatlength)
-   getsize = fatlength;
+   startblock += mydata->fat_sect;
 
/* Write FAT buf */
if (disk_write(startblock, getsize, bufptr) < 0) {
@@ -187,8 +188,9 @@ static __u32 get_fatent_value(fsdata *mydata, __u32 entry)
__u32 fatlength = mydata->fatlength;
__u32 startblock = bufnum * FATBUFBLOCKS;
 
-   if (getsize > fatlength)
-   getsize = fatlength;
+   /* Cap length if fatlength is not a multiple of FATBUFBLOCKS */
+   if (startblock + getsize > fatlength)
+   getsize = fatlength - startblock;
 
startblock += mydata->fat_sect; /* Offset from start of disk */
 
@@ -494,15 +496,15 @@ static int set_fatent_value(fsdata *mydata, __u32 entry, 
__u32 entry_value)
__u32 fatlength = mydata->fatlength;
__u32 startblock = bufnum * FATBUFBLOCKS;
 
-   fatlength *= mydata->sect_size;
-   startblock += mydata->fat_sect;
-
-   if (getsize > fatlength)
-   getsize = fatlength;
+   /* Cap length if fatlength is not a multiple of FATBUFBLOCKS */
+   if (startblock + getsize > fatlength)
+   getsize = fatlength - startblock;
 
if (flush_dirty_fat_buffer(mydata) < 0)
return -1;
 
+   startblock += mydata->fat_sect;
+
if (disk_read(startblock, getsize, bufptr) < 0) {
debug("Error reading FAT blocks\n");
return -1;
-- 
2.11.0

___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


[U-Boot] [PATCH v2 2/2] test/py: Create tests for ext4 and fat testing on sandbox

2016-12-04 Thread Stefan Brüns
From: Stefan Brüns <stefan.bru...@rwth-aachen.de>

The following checks are currently implemented:
1. listing a directory
2. verifying size of a file
3. veryfying md5sum for a file region
4. reading the beginning of a file

Signed-off-by: Stefan Brüns <stefan.bru...@rwth-aachen.de>
---
 test/py/tests/test_fs.py | 357 +++
 1 file changed, 357 insertions(+)
 create mode 100644 test/py/tests/test_fs.py

diff --git a/test/py/tests/test_fs.py b/test/py/tests/test_fs.py
new file mode 100644
index 00..7aaf8debaf
--- /dev/null
+++ b/test/py/tests/test_fs.py
@@ -0,0 +1,357 @@
+# Copyright (c) 2016, Stefan Bruens <stefan.bru...@rwth-aachen.de>
+#
+# SPDX-License-Identifier: GPL-2.0
+
+# Test U-Boot's filesystem implementations
+#
+# The tests are currently covering the ext4 and fat filesystem implementations.
+#
+# Following functionality is currently checked:
+# - Listing a directory and checking for a set of files
+# - Verifying the size of a file
+# - Reading sparse and non-sparse files
+# - File content verification using md5sums
+
+
+from distutils.spawn import find_executable
+import hashlib
+import pytest
+import os
+import random
+import re
+import u_boot_utils as util
+
+@pytest.fixture(scope='session')
+def prereq_commands():
+"""Detect required commands to run file system tests."""
+for command in ['mkfs', 'mount', 'umount']:
+if find_executable(command) is None:
+pytest.skip('Filesystem tests, "{0}" not in PATH'.format(command))
+
+"""
+Scenarios:
+hostfs: access image contents through the sandbox hostfs
+facility, using the filesytem implementation of
+the sandbox host, e.g. Linux kernel
+generic: test u-boots native filesystem implementations,
+using the 'generic' command names, e.g. 'load'
+TODO -
+fscommands: test u-boots native filesystem implementations,
+using the fs specific commands, e.g. 'ext4load'
+"""
+@pytest.fixture(scope='class', params=['generic', 'hostfs'])
+def scenario(request):
+request.cls.scenario = request.param
+return request.param
+
+
+"""
+Dictionary of files to use during filesystem tests. The files
+are keyed by the filenames. The value is an array of strides, each tuple
+contains the the start offset (inclusive) and end offset (exclusive).
+"""
+files = {
+'empty.file' : [(0, 0)],
+'1MB.file'   : [(0, 1e6)],
+'1MB.sparse.file'   : [(1e6-1, 1e6)],
+'32MB.sparse.file'   : [(0, 1e6), (4e6, 5e6), (31e6, 32e6)],
+# Creating a 2.5 GB file on FAT is exceptionally slow, disable it for now
+# '2_5GB.sparse.file'   : [(0, 1e6), (1e9, 1e9+1e6), (2.5e9-1e6, 2.5e9)],
+}
+
+"""Options to pass to mkfs."""
+mkfs_opts = {
+   'fat' :'-t vfat',
+   'ext4' : '-t ext4 -F',
+}
+
+class FsImage:
+def __init__(self, fstype, imagepath, mountpath):
+"""Create a new filesystem image.
+
+Args:
+fstype: filesystem type (string)
+imagepath: full path to image file
+mountpath: mountpoint directory
+"""
+self.fstype = fstype
+self.imagepath = imagepath
+self.mountpath = mountpath
+self.md5s = {}
+with open(self.imagepath, 'w') as fd:
+fd.truncate(0)
+fd.seek(3e9)
+fd.write(bytes([0]))
+
+def mkfs(self, log):
+mkfsopts = mkfs_opts.get(self.fstype)
+util.run_and_log(log,
+'mkfs {0} {1}'.format(mkfsopts, self.imagepath))
+
+def create_file(self, log, filename, strides):
+"""Create a single file in the filesystem. Each file
+is defined by one or more strides, which is filled with
+random data. For each stride, the md5sum is calculated
+and stored.
+"""
+md5sums = []
+with open(self.mountpath + '/' + filename, 'w') as fd:
+for stride in strides:
+length = int(stride[1] - stride[0])
+data = bytearray(random.getrandbits(8) for _ in xrange(length))
+md5 = hashlib.md5(data).hexdigest()
+md5sums.append(md5)
+log.info('{0}: write {1} bytes @ {2} : {3}'.format(
+filename, int(stride[1] - stride[0]),
+int(stride[0]), md5))
+fd.seek(stride[0])
+fd.write(data);
+self.md5s[filename] = md5sums
+
+def create_files(self, log):
+with log.section('Create initial files'):
+for filename in files:
+self.create_file(log, filename, files[filename])
+log.info('Created test files in "{0}"'.format(self.mountpath))
+util.run_and_log(log, 'ls -la {0}'.format(self.mountpath))
+

[U-Boot] [PATCH v2 1/2] test/py: Allow to pass u_boot_log instead of console for run_and_log

2016-12-04 Thread Stefan Brüns
The runner actually has no console dependency, only on the log provided
by the console. Accept both u_boot_console or a multiplexed_log.

Signed-off-by: Stefan Brüns <stefan.bru...@rwth-aachen.de>
---
 test/py/u_boot_utils.py | 20 ++--
 1 file changed, 14 insertions(+), 6 deletions(-)

diff --git a/test/py/u_boot_utils.py b/test/py/u_boot_utils.py
index 2ba4baed07..b9a72ab1de 100644
--- a/test/py/u_boot_utils.py
+++ b/test/py/u_boot_utils.py
@@ -153,11 +153,11 @@ def wait_until_file_open_fails(fn, ignore_errors):
 return
 raise Exception('File can still be opened')
 
-def run_and_log(u_boot_console, cmd, ignore_errors=False):
+def run_and_log(u_boot_console_or_log, cmd, ignore_errors=False):
 """Run a command and log its output.
 
 Args:
-u_boot_console: A console connection to U-Boot.
+u_boot_console_or_log: A console connection to U-Boot, or a LogFile.
 cmd: The command to run, as an array of argv[], or a string.
 If a string, note that it is split up so that quoted spaces
 will not be preserved. E.g. "fred and" becomes ['"fred', 'and"']
@@ -171,25 +171,33 @@ def run_and_log(u_boot_console, cmd, ignore_errors=False):
 """
 if isinstance(cmd, str):
 cmd = cmd.split()
-runner = u_boot_console.log.get_runner(cmd[0], sys.stdout)
+if hasattr(u_boot_console_or_log, 'get_runner'):
+get_runner = u_boot_console_or_log.get_runner
+else:
+get_runner = u_boot_console_or_log.log.get_runner
+runner = get_runner(cmd[0], sys.stdout)
 output = runner.run(cmd, ignore_errors=ignore_errors)
 runner.close()
 return output
 
-def run_and_log_expect_exception(u_boot_console, cmd, retcode, msg):
+def run_and_log_expect_exception(u_boot_console_or_log, cmd, retcode, msg):
 """Run a command that is expected to fail.
 
 This runs a command and checks that it fails with the expected return code
 and exception method. If not, an exception is raised.
 
 Args:
-u_boot_console: A console connection to U-Boot.
+u_boot_console_or_log: A console connection to U-Boot, or a LogFile.
 cmd: The command to run, as an array of argv[].
 retcode: Expected non-zero return code from the command.
 msg: String that should be contained within the command's output.
 """
+if hasattr(u_boot_console_or_log, 'get_runner'):
+get_runner = u_boot_console_or_log.get_runner
+else:
+get_runner = u_boot_console_or_log.log.get_runner
+runner = get_runner(cmd[0], sys.stdout)
 try:
-runner = u_boot_console.log.get_runner(cmd[0], sys.stdout)
 runner.run(cmd)
 except Exception as e:
 assert(retcode == runner.exit_status)
-- 
2.11.0

___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


[U-Boot] [PATCH v2 1/2] ext4: Allow reading files with non-zero offset, clamp read len

2016-11-06 Thread Stefan Brüns
Support was already implemented, but not hooked up. This fixes several
fails in the test cases.

Signed-off-by: Stefan Brüns <stefan.bru...@rwth-aachen.de>
---
v2:
 - update ext4fs_read(...) calls from spl_ext.c
 - move clamping to ext4fs_read_file(...), i.e. correct the check
   for offset != 0

 common/spl/spl_ext.c |  8 
 fs/ext4/ext4fs.c | 17 ++---
 include/ext4fs.h |  2 +-
 3 files changed, 11 insertions(+), 16 deletions(-)

diff --git a/common/spl/spl_ext.c b/common/spl/spl_ext.c
index b93e1ea..1b8e15e 100644
--- a/common/spl/spl_ext.c
+++ b/common/spl/spl_ext.c
@@ -42,7 +42,7 @@ int spl_load_image_ext(struct spl_image_info *spl_image,
puts("spl: ext4fs_open failed\n");
goto end;
}
-   err = ext4fs_read((char *)header, sizeof(struct image_header), );
+   err = ext4fs_read((char *)header, 0, sizeof(struct image_header), 
);
if (err < 0) {
puts("spl: ext4fs_read failed\n");
goto end;
@@ -54,7 +54,7 @@ int spl_load_image_ext(struct spl_image_info *spl_image,
goto end;
}
 
-   err = ext4fs_read((char *)spl_image->load_addr, filelen, );
+   err = ext4fs_read((char *)spl_image->load_addr, 0, filelen, );
 
 end:
 #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
@@ -97,7 +97,7 @@ int spl_load_image_ext_os(struct spl_image_info *spl_image,
puts("spl: ext4fs_open failed\n");
goto defaults;
}
-   err = ext4fs_read((void *)CONFIG_SYS_SPL_ARGS_ADDR, filelen, 
);
+   err = ext4fs_read((void *)CONFIG_SYS_SPL_ARGS_ADDR, 0, filelen, 
);
if (err < 0) {
printf("spl: error reading image %s, err - %d, falling 
back to default\n",
   file, err);
@@ -127,7 +127,7 @@ defaults:
if (err < 0)
puts("spl: ext4fs_open failed\n");
 
-   err = ext4fs_read((void *)CONFIG_SYS_SPL_ARGS_ADDR, filelen, );
+   err = ext4fs_read((void *)CONFIG_SYS_SPL_ARGS_ADDR, 0, filelen, 
);
if (err < 0) {
 #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
printf("%s: error reading image %s, err - %d\n",
diff --git a/fs/ext4/ext4fs.c b/fs/ext4/ext4fs.c
index 3078737..7187dcf 100644
--- a/fs/ext4/ext4fs.c
+++ b/fs/ext4/ext4fs.c
@@ -65,8 +65,8 @@ int ext4fs_read_file(struct ext2fs_node *node, loff_t pos,
short status;
 
/* Adjust len so it we can't read past the end of the file. */
-   if (len > filesize)
-   len = filesize;
+   if (len + pos > filesize)
+   len = (filesize - pos);
 
blockcnt = lldiv(((len + pos) + blocksize - 1), blocksize);
 
@@ -190,12 +190,12 @@ int ext4fs_size(const char *filename, loff_t *size)
return ext4fs_open(filename, size);
 }
 
-int ext4fs_read(char *buf, loff_t len, loff_t *actread)
+int ext4fs_read(char *buf, loff_t offset, loff_t len, loff_t *actread)
 {
if (ext4fs_root == NULL || ext4fs_file == NULL)
-   return 0;
+   return -1;
 
-   return ext4fs_read_file(ext4fs_file, 0, len, buf, actread);
+   return ext4fs_read_file(ext4fs_file, offset, len, buf, actread);
 }
 
 int ext4fs_probe(struct blk_desc *fs_dev_desc,
@@ -217,11 +217,6 @@ int ext4_read_file(const char *filename, void *buf, loff_t 
offset, loff_t len,
loff_t file_len;
int ret;
 
-   if (offset != 0) {
-   printf("** Cannot support non-zero offset **\n");
-   return -1;
-   }
-
ret = ext4fs_open(filename, _len);
if (ret < 0) {
printf("** File not found %s **\n", filename);
@@ -231,7 +226,7 @@ int ext4_read_file(const char *filename, void *buf, loff_t 
offset, loff_t len,
if (len == 0)
len = file_len;
 
-   return ext4fs_read(buf, len, len_read);
+   return ext4fs_read(buf, offset, len, len_read);
 }
 
 int ext4fs_uuid(char *uuid_str)
diff --git a/include/ext4fs.h b/include/ext4fs.h
index 965cd9e..bb55639 100644
--- a/include/ext4fs.h
+++ b/include/ext4fs.h
@@ -135,7 +135,7 @@ int ext4_write_file(const char *filename, void *buf, loff_t 
offset, loff_t len,
 
 struct ext_filesystem *get_fs(void);
 int ext4fs_open(const char *filename, loff_t *len);
-int ext4fs_read(char *buf, loff_t len, loff_t *actread);
+int ext4fs_read(char *buf, loff_t offset, loff_t len, loff_t *actread);
 int ext4fs_mount(unsigned part_length);
 void ext4fs_close(void);
 void ext4fs_reinit_global(void);
-- 
2.10.1

___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


[U-Boot] [PATCH 2/2] fs-test.sh: Update expected results

2016-11-05 Thread Stefan Brüns
After the latest changes, ext4 no longer has any fails.

Signed-off-by: Stefan Brüns <stefan.bru...@rwth-aachen.de>
---
 test/fs/fs-test.sh | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/test/fs/fs-test.sh b/test/fs/fs-test.sh
index 6e71b61..b194864 100755
--- a/test/fs/fs-test.sh
+++ b/test/fs/fs-test.sh
@@ -10,13 +10,13 @@
 # Expected results are as follows:
 # EXT4 tests:
 # fs-test.sb.ext4.out: Summary: PASS: 23 FAIL: 0
-# fs-test.ext4.out: Summary: PASS: 14 FAIL: 9
-# fs-test.fs.ext4.out: Summary: PASS: 14 FAIL: 9
+# fs-test.ext4.out: Summary: PASS: 23 FAIL: 0
+# fs-test.fs.ext4.out: Summary: PASS: 23 FAIL: 0
 # FAT tests:
 # fs-test.sb.fat.out: Summary: PASS: 23 FAIL: 0
 # fs-test.fat.out: Summary: PASS: 20 FAIL: 3
 # fs-test.fs.fat.out: Summary: PASS: 20 FAIL: 3
-# Total Summary: TOTAL PASS: 114 TOTAL FAIL: 24
+# Total Summary: TOTAL PASS: 132 TOTAL FAIL: 6
 
 # pre-requisite binaries list.
 PREREQ_BINS="md5sum mkfs mount umount dd fallocate mkdir"
-- 
2.10.1

___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


[U-Boot] [PATCH 1/2] ext4: Allow reading files with non-zero offset, clamp read len

2016-11-05 Thread Stefan Brüns
Support was already implemented, but not hooked up. This fixes several
fails in the test cases.

Signed-off-by: Stefan Brüns <stefan.bru...@rwth-aachen.de>
---
 fs/ext4/ext4fs.c | 15 +--
 include/ext4fs.h |  2 +-
 2 files changed, 6 insertions(+), 11 deletions(-)

diff --git a/fs/ext4/ext4fs.c b/fs/ext4/ext4fs.c
index 3078737..f8cf6cd 100644
--- a/fs/ext4/ext4fs.c
+++ b/fs/ext4/ext4fs.c
@@ -190,12 +190,12 @@ int ext4fs_size(const char *filename, loff_t *size)
return ext4fs_open(filename, size);
 }
 
-int ext4fs_read(char *buf, loff_t len, loff_t *actread)
+int ext4fs_read(char *buf, loff_t offset, loff_t len, loff_t *actread)
 {
if (ext4fs_root == NULL || ext4fs_file == NULL)
return 0;
 
-   return ext4fs_read_file(ext4fs_file, 0, len, buf, actread);
+   return ext4fs_read_file(ext4fs_file, offset, len, buf, actread);
 }
 
 int ext4fs_probe(struct blk_desc *fs_dev_desc,
@@ -217,21 +217,16 @@ int ext4_read_file(const char *filename, void *buf, 
loff_t offset, loff_t len,
loff_t file_len;
int ret;
 
-   if (offset != 0) {
-   printf("** Cannot support non-zero offset **\n");
-   return -1;
-   }
-
ret = ext4fs_open(filename, _len);
if (ret < 0) {
printf("** File not found %s **\n", filename);
return -1;
}
 
-   if (len == 0)
-   len = file_len;
+   if ((len == 0) || (offset + len > file_len))
+   len = (file_len - offset);
 
-   return ext4fs_read(buf, len, len_read);
+   return ext4fs_read(buf, offset, len, len_read);
 }
 
 int ext4fs_uuid(char *uuid_str)
diff --git a/include/ext4fs.h b/include/ext4fs.h
index 965cd9e..bb55639 100644
--- a/include/ext4fs.h
+++ b/include/ext4fs.h
@@ -135,7 +135,7 @@ int ext4_write_file(const char *filename, void *buf, loff_t 
offset, loff_t len,
 
 struct ext_filesystem *get_fs(void);
 int ext4fs_open(const char *filename, loff_t *len);
-int ext4fs_read(char *buf, loff_t len, loff_t *actread);
+int ext4fs_read(char *buf, loff_t offset, loff_t len, loff_t *actread);
 int ext4fs_mount(unsigned part_length);
 void ext4fs_close(void);
 void ext4fs_reinit_global(void);
-- 
2.10.1

___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


[U-Boot] [PATCH] ext4: Fix handling of sparse files

2016-11-05 Thread Stefan Brüns
A sparse file may have regions not mapped by any extents, at the start
or at the end of the file, or anywhere between, thus not finding a
matching extent region is never an error.

Found by python filesystem tests.

Signed-off-by: Stefan Brüns <stefan.bru...@rwth-aachen.de>
---
 fs/ext4/ext4_common.c | 31 +++
 1 file changed, 15 insertions(+), 16 deletions(-)

diff --git a/fs/ext4/ext4_common.c b/fs/ext4/ext4_common.c
index 4248ac1..bfebe7e 100644
--- a/fs/ext4/ext4_common.c
+++ b/fs/ext4/ext4_common.c
@@ -1617,12 +1617,13 @@ long int read_allocated_block(struct ext2_inode *inode, 
int fileblock)
- get_fs()->dev_desc->log2blksz;
 
if (le32_to_cpu(inode->flags) & EXT4_EXTENTS_FL) {
+   long int startblock, endblock;
char *buf = zalloc(blksz);
if (!buf)
return -ENOMEM;
struct ext4_extent_header *ext_block;
struct ext4_extent *extent;
-   int i = -1;
+   int i;
ext_block =
ext4fs_get_extent_block(ext4fs_root, buf,
(struct ext4_extent_header *)
@@ -1636,28 +1637,26 @@ long int read_allocated_block(struct ext2_inode *inode, 
int fileblock)
 
extent = (struct ext4_extent *)(ext_block + 1);
 
-   do {
-   i++;
-   if (i >= le16_to_cpu(ext_block->eh_entries))
-   break;
-   } while (fileblock >= le32_to_cpu(extent[i].ee_block));
-   if (--i >= 0) {
-   fileblock -= le32_to_cpu(extent[i].ee_block);
-   if (fileblock >= le16_to_cpu(extent[i].ee_len)) {
+   for (i = 0; i < le16_to_cpu(ext_block->eh_entries); i++) {
+   startblock = le32_to_cpu(extent[i].ee_block);
+   endblock = startblock + le16_to_cpu(extent[i].ee_len);
+
+   if (startblock > fileblock) {
+   /* Sparse file */
free(buf);
return 0;
-   }
 
-   start = le16_to_cpu(extent[i].ee_start_hi);
-   start = (start << 32) +
+   } else if (fileblock < endblock) {
+   start = le16_to_cpu(extent[i].ee_start_hi);
+   start = (start << 32) +
le32_to_cpu(extent[i].ee_start_lo);
-   free(buf);
-   return fileblock + start;
+   free(buf);
+   return (fileblock - startblock) + start;
+   }
}
 
-   printf("Extent Error\n");
free(buf);
-   return -1;
+   return 0;
}
 
/* Direct blocks. */
-- 
2.10.1

___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


[U-Boot] [PATCH 1/3] test/py: expose config and log as session scoped fixture

2016-11-05 Thread Stefan Brüns
If a test uses a fixture which is expensive to setup, the fixture can
possibly created with session or module scope. As u_boot_console has
function scope, it can not be used in this case.

Signed-off-by: Stefan Brüns <stefan.bru...@rwth-aachen.de>
---
 test/py/conftest.py | 26 ++
 1 file changed, 26 insertions(+)

diff --git a/test/py/conftest.py b/test/py/conftest.py
index 1f15e3e..65e1d75 100644
--- a/test/py/conftest.py
+++ b/test/py/conftest.py
@@ -298,6 +298,32 @@ def pytest_generate_tests(metafunc):
 continue
 generate_config(metafunc, fn)
 
+@pytest.fixture(scope='session')
+def u_boot_log(request):
+ """Generate the value of a test's log fixture.
+
+ Args:
+ request: The pytest request.
+
+ Returns:
+ The fixture value.
+ """
+
+ return console.log
+
+@pytest.fixture(scope='session')
+def u_boot_config(request):
+ """Generate the value of a test's u_boot_config fixture.
+
+ Args:
+ request: The pytest request.
+
+ Returns:
+ The fixture value.
+ """
+
+ return console.config
+
 @pytest.fixture(scope='function')
 def u_boot_console(request):
 """Generate the value of a test's u_boot_console fixture.
-- 
2.10.1

___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


[U-Boot] [PATCH 2/3] test/py: Allow to pass u_boot_log instead of console for run_and_log

2016-11-05 Thread Stefan Brüns
The runner actually has no console dependency, only on the log provided
by the console. Accept both u_boot_console or a multiplexed_log.

Signed-off-by: Stefan Brüns <stefan.bru...@rwth-aachen.de>
---
 test/py/u_boot_utils.py | 10 --
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/test/py/u_boot_utils.py b/test/py/u_boot_utils.py
index 2ba4bae..c80cf07 100644
--- a/test/py/u_boot_utils.py
+++ b/test/py/u_boot_utils.py
@@ -153,7 +153,7 @@ def wait_until_file_open_fails(fn, ignore_errors):
 return
 raise Exception('File can still be opened')
 
-def run_and_log(u_boot_console, cmd, ignore_errors=False):
+def run_and_log(u_boot_console_or_log, cmd, ignore_errors=False):
 """Run a command and log its output.
 
 Args:
@@ -171,7 +171,10 @@ def run_and_log(u_boot_console, cmd, ignore_errors=False):
 """
 if isinstance(cmd, str):
 cmd = cmd.split()
-runner = u_boot_console.log.get_runner(cmd[0], sys.stdout)
+try:
+runner = u_boot_console_or_log.get_runner(cmd[0], sys.stdout)
+except:
+runner = u_boot_console_or_log.log.get_runner(cmd[0], sys.stdout)
 output = runner.run(cmd, ignore_errors=ignore_errors)
 runner.close()
 return output
@@ -189,7 +192,10 @@ def run_and_log_expect_exception(u_boot_console, cmd, 
retcode, msg):
 msg: String that should be contained within the command's output.
 """
 try:
+runner = u_boot_console.get_runner(cmd[0], sys.stdout)
+except:
 runner = u_boot_console.log.get_runner(cmd[0], sys.stdout)
+try:
 runner.run(cmd)
 except Exception as e:
 assert(retcode == runner.exit_status)
-- 
2.10.1

___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


[U-Boot] [PATCH 3/3] test/py: Create tests for ext4 and fat testing on sandbox

2016-11-05 Thread Stefan Brüns
The following checks are currently implemented:
1. listing a directory
2. verifying size of a file
3. veryfying md5sum for a file region
4. reading the beginning of a file

Signed-off-by: Stefan Brüns <stefan.bru...@rwth-aachen.de>
---
 test/py/tests/test_fs.py | 298 +++
 1 file changed, 298 insertions(+)
 create mode 100644 test/py/tests/test_fs.py

diff --git a/test/py/tests/test_fs.py b/test/py/tests/test_fs.py
new file mode 100644
index 000..5ac91e4
--- /dev/null
+++ b/test/py/tests/test_fs.py
@@ -0,0 +1,298 @@
+# Copyright (c) 2016, Stefan Bruens <stefan.bru...@rwth-aachen.de>
+#
+# SPDX-License-Identifier: GPL-2.0
+
+# Test U-Boot's filesystem implementations
+
+import hashlib
+import pytest
+import os
+import random
+import re
+import u_boot_utils as util
+
+
+mkfs_opts = {
+   "fat" :'-t vfat',
+   "ext4" : '-t ext4 -F',
+}
+
+fs_commands = {
+   "fat" : {
+   'listcmd'   : 'ls',
+   'readcmd'   : 'load',
+   'sizecmd'   : 'size',
+   'writecmd'  : 'size',
+   },
+   "ext4" : {
+   'listcmd'   : 'ls',
+   'readcmd'   : 'load',
+   'sizecmd'   : 'size',
+   'writecmd'  : 'size',
+   },
+}
+
+cmd_parameters = {
+   "hostfs" : {
+   'prefix': 'host ',
+   'interface' : 'hostfs -',
+   },
+   "generic" : {
+   'prefix': '',
+   'interface' : 'host 0:0',
+   },
+}
+
+files = {
+"empty.file" : [(0, 0)],
+"1MB.file"   : [(0, 1e6)],
+"1MB.sparse.file"   : [(1e6-1, 1e6)],
+}
+# "2_5GB.sparse.file"   : [(0, 1e6), (1e9, 1e9+1e6), (2.5e9-1e6, 2.5e9)],
+
+@pytest.fixture(scope="session")
+def prereq_commands():
+from distutils.spawn import find_executable
+for command in ["mkfs", "mount", "umount"]:
+if find_executable(command) is None:
+pytest.skip('Filesystem tests, "{0}" not in PATH'.format(command))
+
+class FsImage:
+def __init__(self, fstype, imagename, mountpath):
+self.fstype = fstype
+self.imagename = imagename
+self.mountpath = mountpath
+self.md5s = {}
+with open(self.imagename, 'w') as fd:
+fd.truncate(0)
+fd.seek(3e9)
+fd.write(bytes([0]))
+
+def mkfs(self, log):
+mkfsopts = mkfs_opts.get(self.fstype)
+util.run_and_log(log,
+'mkfs {0} {1}'.format(mkfsopts, self.imagename))
+
+def create_file(self, log, filename):
+md5sums = []
+with open(self.mountpath + "/" + filename, 'w') as fd:
+for stride in files[filename]:
+length = int(stride[1] - stride[0])
+data = bytearray(random.getrandbits(8) for _ in xrange(length))
+md5 = hashlib.md5(data).hexdigest()
+md5sums.append(md5)
+log.info("{0}: write {1} bytes @ {2} : {3}".format(
+filename, int(stride[1] - stride[0]),
+int(stride[0]), md5))
+fd.seek(stride[0])
+fd.write(data);
+self.md5s[filename] = md5sums
+
+def create_files(self, log):
+with log.section("Create initial files"):
+for filename in files:
+self.create_file(log, filename)
+log.info("Created test files in {0}".format(self.mountpath))
+util.run_and_log(log, 'ls -la {0}'.format(self.mountpath))
+util.run_and_log(log, 'sync {0}'.format(self.mountpath))
+
+def mount(self, log):
+if not os.path.exists(self.mountpath):
+os.mkdir(self.mountpath)
+log.info("Mounting {0} at {1}".format(self.imagename, self.mountpath))
+if self.fstype == "ext4":
+cmd = 'sudo -n mount -o loop,rw {0} {1}'.format(self.imagename, 
self.mountpath)
+else:
+cmd = 'sudo -n mount -o loop,rw,umask=000 {0} 
{1}'.format(self.imagename, self.mountpath)
+util.run_and_log(log, cmd)
+if self.fstype == "ext4":
+cmd = 'sudo -n chmod og+rw {0}'.format(self.mountpath)
+return util.run_and_log(log, cmd)
+
+def unmount(self, log):
+log.info("Unmounting {0}".format(self.imagename))
+cmd = 'sudo -n umount -l {0}'.format(self.mountpath)
+util.run_and_log(log, cmd, ignore_errors=True)
+
+
+@pytest.fixture(scope="module", params=["fat", "ext4"])
+def fsimage(prereq_commands, u_boot_config, u_boot_log, request):
+datadir = u_boot_config.result_dir + '/'
+fstype = request.param
+imagename = datadir + "3GB." + fstype + ".img"
+mountpath = datadir + &q

[U-Boot] [PATCH 0/3] Create python filesystem tests

2016-11-05 Thread Stefan Brüns
This is a first attempt to create filesystem tests in python. It is currently
targetting sandbox, although it should be possible to make it work with e.g.
the qemu based testruns.

First two patches are prep work, first patch is copied verbatim from a mail
from Stephen Warren.

The actual tests are in patch 3. CUrrently it is a subset of what can be tested
with the old shell script, most importantly no write tests.

The following tests are currently implemented:
1. Listing a directory and checking for a set of files
2. Verifying the size of a file
3. Verifying the md5sums of specified regions of a file
4. Reading the head of a file

3. and 4. have some overlap, but the latter will also read sparse file regions.

As the old test, some parts need root privileges to mount the image.

Stefan Brüns (3):
  test/py: expose config and log as session scoped fixture
  test/py: Allow to pass u_boot_log instead of console for run_and_log
  test/py: Create tests for ext4 and fat testing on sandbox

 test/py/conftest.py  |  26 +
 test/py/tests/test_fs.py | 298 +++
 test/py/u_boot_utils.py  |  10 +-
 3 files changed, 332 insertions(+), 2 deletions(-)
 create mode 100644 test/py/tests/test_fs.py

-- 
2.10.1

___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


[U-Boot] [PATCH] tools: add mksunxiboot to tools-all target

2016-10-29 Thread Stefan Brüns
mksunxiboot is useful outside of u-boot, it is e.g. used by sunxi-tools.

Signed-off-by: Stefan Brüns <stefan.bru...@rwth-aachen.de>
---
 tools/Makefile  | 1 +
 tools/mksunxiboot.c | 2 +-
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/tools/Makefile b/tools/Makefile
index e6f7993..8e6dede 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -13,6 +13,7 @@ CONFIG_CMD_NET = y
 CONFIG_XWAY_SWAP_BYTES = y
 CONFIG_NETCONSOLE = y
 CONFIG_SHA1_CHECK_UB_IMG = y
+CONFIG_SUNXI = y
 endif
 
 subdir-$(HOST_TOOLS_ALL) += easylogo
diff --git a/tools/mksunxiboot.c b/tools/mksunxiboot.c
index 9c1c5b7..0f0b003 100644
--- a/tools/mksunxiboot.c
+++ b/tools/mksunxiboot.c
@@ -15,7 +15,7 @@
 #include 
 #include 
 #include 
-#include "asm/arch/spl.h"
+#include "../arch/arm/include/asm/arch-sunxi/spl.h"
 
 #define STAMP_VALUE 0x5F0A6C39
 
-- 
2.10.1

___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


[U-Boot] [PATCH] test/py: Fix exception, do not parametrize with empty set

2016-10-16 Thread Stefan Brüns
If the parameter set is empty, the pytest setup fails:
---
call: 
---

This aborts pytest_runtest_makereport and later leads to an exception
during the report generation, as the call to log.start_section(...)
is never executed:
---
Exception: Block nesting mismatch:
"test_dfu[env__usb_dev_port0-env__dfu_config0]" ""
---

Signed-off-by: Stefan Brüns <stefan.bru...@rwth-aachen.de>
---
 test/py/conftest.py | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/test/py/conftest.py b/test/py/conftest.py
index 5b3a923..ebef40d 100644
--- a/test/py/conftest.py
+++ b/test/py/conftest.py
@@ -270,6 +270,8 @@ def generate_config(metafunc, fixture_name):
 # ... otherwise, see if there's a key that contains a list of
 # values to use instead.
 vals = subconfig.get(fixture_name+ 's', [])
+if len(vals) == 0:
+return
 def fixture_id(index, val):
 try:
 return val['fixture_id']
-- 
2.10.1

___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


[U-Boot] [PATCH] cmd/tpm_test: Fix misleading code indentation

2016-10-16 Thread Stefan Brüns
GCC 6.2 reasonably complains about the current code:

../cmd/tpm_test.c: In function ‘do_tpmtest’:
../cmd/tpm_test.c:540:3: warning: this ‘for’ clause does not guard... 
[-Wmisleading-indentation]
   for (i = 0; i < argc; i++)
   ^~~
../cmd/tpm_test.c:542:4: note: ...this statement, but the latter is 
misleadingly indented as if it is guarded by the ‘for’
printf("\n--\n");
^~

Signed-off-by: Stefan Brüns <stefan.bru...@rwth-aachen.de>
---
 cmd/tpm_test.c | 11 +--
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/cmd/tpm_test.c b/cmd/tpm_test.c
index 65332d1..4af4d71 100644
--- a/cmd/tpm_test.c
+++ b/cmd/tpm_test.c
@@ -534,13 +534,12 @@ static int do_tpmtest(cmd_tbl_t *cmdtp, int flag, int 
argc, char * const argv[])
cmd_tbl_t *c;
 
printf("argc = %d, argv = ", argc);
-   do {
-   int i = 0;
 
-   for (i = 0; i < argc; i++)
-   printf(" %s", argv[i]);
-   printf("\n--\n");
-   } while (0);
+   for (int i = 0; i < argc; i++)
+   printf(" %s", argv[i]);
+
+   printf("\n--\n");
+
argc--;
argv++;
c = find_cmd_tbl(argv[0], cmd_cros_tpm_sub,
-- 
2.10.1

___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


[U-Boot] [PATCH v4 2/7] efi_loader: Fix memory map size check to avoid out-of-bounds access

2016-10-09 Thread Stefan Brüns
The current efi_get_memory_map() function overwrites the map_size
property before reading its value. That way the sanity check whether our
memory map fits into the given array always succeeds, potentially
overwriting arbitrary payload memory.

This patch moves the property update write after its sanity check, so
that the check actually verifies the correct value.

So far this has not triggered any known bugs, but we're better off safe
than sorry.

If the buffer is to small, the returned memory_map_size indicates the
required size to the caller.

Signed-off-by: Stefan Brüns <stefan.bru...@rwth-aachen.de>
---
 lib/efi_loader/efi_memory.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c
index ebe8e94..1d23783 100644
--- a/lib/efi_loader/efi_memory.c
+++ b/lib/efi_loader/efi_memory.c
@@ -336,6 +336,7 @@ efi_status_t efi_get_memory_map(unsigned long 
*memory_map_size,
ulong map_size = 0;
int map_entries = 0;
struct list_head *lhandle;
+   unsigned long provided_map_size = *memory_map_size;
 
list_for_each(lhandle, _mem)
map_entries++;
@@ -350,7 +351,7 @@ efi_status_t efi_get_memory_map(unsigned long 
*memory_map_size,
if (descriptor_version)
*descriptor_version = EFI_MEMORY_DESCRIPTOR_VERSION;
 
-   if (*memory_map_size < map_size)
+   if (provided_map_size < map_size)
return EFI_BUFFER_TOO_SMALL;
 
/* Copy list into array */
-- 
2.10.0

___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


[U-Boot] [PATCH v4 4/7] efi_loader: Track size of pool allocations to allow freeing

2016-10-09 Thread Stefan Brüns
We need a functional free_pool implementation, as otherwise each
allocate_pool causes growth of the memory descriptor table.

Different to free_pages, free_pool does not provide the size for the
to be freed allocation, thus we have to track the size ourselves.

As the only EFI requirement for pool allocation is an alignment of
8 bytes, we can keep allocating a range using the page allocator,
reserve the first 8 bytes for our bookkeeping and hand out the
remainder to the caller. This saves us from having to use any
independent data structures for tracking.

To simplify the conversion between pool allocations and the corresponding
page allocation, we create an auxiliary struct efi_pool_allocation.

Given the allocation size free_pool size can handoff freeing the page
range, which was indirectly allocated by a call to allocate_pool,
to free_pages.

Signed-off-by: Stefan Brüns <stefan.bru...@rwth-aachen.de>
---
 include/efi_loader.h  |  2 ++
 lib/efi_loader/efi_boottime.c |  6 +++---
 lib/efi_loader/efi_memory.c   | 42 +++---
 3 files changed, 44 insertions(+), 6 deletions(-)

diff --git a/include/efi_loader.h b/include/efi_loader.h
index f0473ab..3dad24e 100644
--- a/include/efi_loader.h
+++ b/include/efi_loader.h
@@ -122,6 +122,8 @@ efi_status_t efi_free_pages(uint64_t memory, unsigned long 
pages);
 /* EFI memory allocator for small allocations */
 efi_status_t efi_allocate_pool(int pool_type, unsigned long size,
   void **buffer);
+/* EFI pool memory free function. */
+efi_status_t efi_free_pool(void *buffer);
 /* Returns the EFI memory map */
 efi_status_t efi_get_memory_map(unsigned long *memory_map_size,
struct efi_mem_desc *memory_map,
diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
index eb74cb0..8274d8e 100644
--- a/lib/efi_loader/efi_boottime.c
+++ b/lib/efi_loader/efi_boottime.c
@@ -141,12 +141,12 @@ static efi_status_t EFIAPI efi_allocate_pool_ext(int 
pool_type,
return EFI_EXIT(r);
 }
 
-static efi_status_t EFIAPI efi_free_pool(void *buffer)
+static efi_status_t EFIAPI efi_free_pool_ext(void *buffer)
 {
efi_status_t r;
 
EFI_ENTRY("%p", buffer);
-   r = efi_free_pages((ulong)buffer, 0);
+   r = efi_free_pool(buffer);
return EFI_EXIT(r);
 }
 
@@ -736,7 +736,7 @@ static const struct efi_boot_services efi_boot_services = {
.free_pages = efi_free_pages_ext,
.get_memory_map = efi_get_memory_map_ext,
.allocate_pool = efi_allocate_pool_ext,
-   .free_pool = efi_free_pool,
+   .free_pool = efi_free_pool_ext,
.create_event = efi_create_event,
.set_timer = efi_set_timer,
.wait_for_event = efi_wait_for_event,
diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c
index be642f1..de28db6 100644
--- a/lib/efi_loader/efi_memory.c
+++ b/lib/efi_loader/efi_memory.c
@@ -34,6 +34,19 @@ void *efi_bounce_buffer;
 #endif
 
 /*
+ * U-Boot services each EFI AllocatePool request as a separate
+ * (multiple) page allocation.  We have to track the number of pages
+ * to be able to free the correct amount later.
+ * EFI requires 8 byte alignment for pool allocations, so we can
+ * prepend each allocation with an 64 bit header tracking the
+ * allocation size, and hand out the remainder to the caller.
+ */
+struct efi_pool_allocation {
+   u64 num_pages;
+   char data[];
+};
+
+/*
  * Sorts the memory list from highest address to lowest address
  *
  * When allocating memory we should always start from the highest
@@ -332,11 +345,34 @@ efi_status_t efi_allocate_pool(int pool_type, unsigned 
long size,
 {
efi_status_t r;
efi_physical_addr_t t;
-   u64 num_pages = (size + EFI_PAGE_MASK) >> EFI_PAGE_SHIFT;
+   u64 num_pages = (size + sizeof(u64) + EFI_PAGE_MASK) >> EFI_PAGE_SHIFT;
+
+   if (size == 0) {
+   *buffer = NULL;
+   return EFI_SUCCESS;
+   }
 
r = efi_allocate_pages(0, pool_type, num_pages, );
-   if (r == EFI_SUCCESS)
-   *buffer = (void *)(uintptr_t)t;
+
+   if (r == EFI_SUCCESS) {
+   struct efi_pool_allocation *alloc = (void *)(uintptr_t)t;
+   alloc->num_pages = num_pages;
+   *buffer = alloc->data;
+   }
+
+   return r;
+}
+
+efi_status_t efi_free_pool(void *buffer)
+{
+   efi_status_t r;
+   struct efi_pool_allocation *alloc;
+
+   alloc = container_of(buffer, struct efi_pool_allocation, data);
+   /* Sanity check, was the supplied address returned by allocate_pool */
+   assert(((uintptr_t)alloc & EFI_PAGE_MASK) == 0);
+
+   r = efi_free_pages((uintptr_t)alloc, alloc->num_pages);
 
return r;
 }
-- 
2.10.0

___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


[U-Boot] [PATCH v4 3/7] efi_loader: Move efi_allocate_pool implementation to efi_memory.c

2016-10-09 Thread Stefan Brüns
We currently handle efi_allocate_pool() in our boot time service
file. In the following patch, pool allocation will receive additional
internal semantics that we should preserve inside efi_memory.c instead.

As foundation for those changes, split the function into an externally
facing efi_allocate_pool_ext() for use by payloads and an internal helper
efi_allocate_pool() in efi_memory.c that handles the actual allocation.

While at it, change the magic 0xfff / 12 constants to the more obvious
EFI_PAGE_MASK/SHIFT defines.

Signed-off-by: Stefan Brüns <stefan.bru...@rwth-aachen.de>
---
 include/efi_loader.h  |  3 +++
 lib/efi_loader/efi_boottime.c | 11 +--
 lib/efi_loader/efi_memory.c   | 14 ++
 3 files changed, 22 insertions(+), 6 deletions(-)

diff --git a/include/efi_loader.h b/include/efi_loader.h
index 9738835..f0473ab 100644
--- a/include/efi_loader.h
+++ b/include/efi_loader.h
@@ -119,6 +119,9 @@ efi_status_t efi_allocate_pages(int type, int memory_type, 
unsigned long pages,
uint64_t *memory);
 /* EFI memory free function. Not implemented today */
 efi_status_t efi_free_pages(uint64_t memory, unsigned long pages);
+/* EFI memory allocator for small allocations */
+efi_status_t efi_allocate_pool(int pool_type, unsigned long size,
+  void **buffer);
 /* Returns the EFI memory map */
 efi_status_t efi_get_memory_map(unsigned long *memory_map_size,
struct efi_mem_desc *memory_map,
diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
index 784891b..eb74cb0 100644
--- a/lib/efi_loader/efi_boottime.c
+++ b/lib/efi_loader/efi_boottime.c
@@ -130,15 +130,14 @@ efi_status_t EFIAPI efi_get_memory_map_ext(unsigned long 
*memory_map_size,
return EFI_EXIT(r);
 }
 
-static efi_status_t EFIAPI efi_allocate_pool(int pool_type, unsigned long size,
-void **buffer)
+static efi_status_t EFIAPI efi_allocate_pool_ext(int pool_type,
+unsigned long size,
+void **buffer)
 {
efi_status_t r;
-   efi_physical_addr_t t;
 
EFI_ENTRY("%d, %ld, %p", pool_type, size, buffer);
-   r = efi_allocate_pages(0, pool_type, (size + 0xfff) >> 12, );
-   *buffer = (void *)(uintptr_t)t;
+   r = efi_allocate_pool(pool_type, size, buffer);
return EFI_EXIT(r);
 }
 
@@ -736,7 +735,7 @@ static const struct efi_boot_services efi_boot_services = {
.allocate_pages = efi_allocate_pages_ext,
.free_pages = efi_free_pages_ext,
.get_memory_map = efi_get_memory_map_ext,
-   .allocate_pool = efi_allocate_pool,
+   .allocate_pool = efi_allocate_pool_ext,
.free_pool = efi_free_pool,
.create_event = efi_create_event,
.set_timer = efi_set_timer,
diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c
index 1d23783..be642f1 100644
--- a/lib/efi_loader/efi_memory.c
+++ b/lib/efi_loader/efi_memory.c
@@ -327,6 +327,20 @@ efi_status_t efi_free_pages(uint64_t memory, unsigned long 
pages)
return EFI_SUCCESS;
 }
 
+efi_status_t efi_allocate_pool(int pool_type, unsigned long size,
+  void **buffer)
+{
+   efi_status_t r;
+   efi_physical_addr_t t;
+   u64 num_pages = (size + EFI_PAGE_MASK) >> EFI_PAGE_SHIFT;
+
+   r = efi_allocate_pages(0, pool_type, num_pages, );
+   if (r == EFI_SUCCESS)
+   *buffer = (void *)(uintptr_t)t;
+
+   return r;
+}
+
 efi_status_t efi_get_memory_map(unsigned long *memory_map_size,
   struct efi_mem_desc *memory_map,
   unsigned long *map_key,
-- 
2.10.0

___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


[U-Boot] [PATCH 1/3] ext4: cleanup unlink_filename function

2016-10-09 Thread Stefan Brüns
Use the same variable names as in search_dir, to make purpose of variables
more obvious.

Signed-off-by: Stefan Brüns <stefan.bru...@rwth-aachen.de>
---
 fs/ext4/ext4_common.c | 29 +++--
 1 file changed, 15 insertions(+), 14 deletions(-)

diff --git a/fs/ext4/ext4_common.c b/fs/ext4/ext4_common.c
index e78185b..699a640 100644
--- a/fs/ext4/ext4_common.c
+++ b/fs/ext4/ext4_common.c
@@ -854,34 +854,35 @@ fail:
 
 static int unlink_filename(char *filename, unsigned int blknr)
 {
-   int totalbytes = 0;
int templength = 0;
int status, inodeno;
int found = 0;
-   char *root_first_block_buffer = NULL;
+   int offset;
+   char *block_buffer = NULL;
struct ext2_dirent *dir = NULL;
struct ext2_dirent *previous_dir = NULL;
char *ptr = NULL;
struct ext_filesystem *fs = get_fs();
int ret = -1;
 
-   /* get the first block of root */
-   root_first_block_buffer = zalloc(fs->blksz);
-   if (!root_first_block_buffer)
+   block_buffer = zalloc(fs->blksz);
+   if (!block_buffer)
return -ENOMEM;
+
+   /* read the directory block */
status = ext4fs_devread((lbaint_t)blknr * fs->sect_perblk, 0,
-   fs->blksz, root_first_block_buffer);
+   fs->blksz, block_buffer);
if (status == 0)
goto fail;
 
-   if (ext4fs_log_journal(root_first_block_buffer, blknr))
+   if (ext4fs_log_journal(block_buffer, blknr))
goto fail;
-   dir = (struct ext2_dirent *)root_first_block_buffer;
+   dir = (struct ext2_dirent *)block_buffer;
ptr = (char *)dir;
-   totalbytes = 0;
+   offset = 0;
while (le16_to_cpu(dir->direntlen) >= 0) {
/*
-* blocksize-totalbytes because last
+* blocksize-offset because last
 * directory length i.e., *dir->direntlen
 * is free availble space in the block that
 * means it is a last entry of directory entry
@@ -903,12 +904,12 @@ static int unlink_filename(char *filename, unsigned int 
blknr)
break;
}
 
-   if (fs->blksz - totalbytes == le16_to_cpu(dir->direntlen))
+   if (fs->blksz - offset == le16_to_cpu(dir->direntlen))
break;
 
/* traversing the each directory entry */
templength = le16_to_cpu(dir->direntlen);
-   totalbytes = totalbytes + templength;
+   offset = offset + templength;
previous_dir = dir;
dir = (struct ext2_dirent *)((char *)dir + templength);
ptr = (char *)dir;
@@ -916,12 +917,12 @@ static int unlink_filename(char *filename, unsigned int 
blknr)
 
 
if (found == 1) {
-   if (ext4fs_put_metadata(root_first_block_buffer, blknr))
+   if (ext4fs_put_metadata(block_buffer, blknr))
goto fail;
ret = inodeno;
}
 fail:
-   free(root_first_block_buffer);
+   free(block_buffer);
 
return ret;
 }
-- 
2.10.0

___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


[U-Boot] [PATCH 2/3] ext4: Fix handling of direntlen in unlink_filename

2016-10-09 Thread Stefan Brüns
The direntlen checks were quite bogus, i.e. the loop termination used
"len + offset == blocksize" (exact match only), and checked for a
direntlen less than 0. The latter can never happen as the len is
unsigned, this has been reported by Coverity, CID 153384.

Use the same code as in search_dir for directory traversal. This code
has the correct checks for direntlen >= sizeof(struct dirent), and
offset < blocksize.

Signed-off-by: Stefan Brüns <stefan.bru...@rwth-aachen.de>
---
 fs/ext4/ext4_common.c | 45 +
 1 file changed, 17 insertions(+), 28 deletions(-)

diff --git a/fs/ext4/ext4_common.c b/fs/ext4/ext4_common.c
index 699a640..11be0b7 100644
--- a/fs/ext4/ext4_common.c
+++ b/fs/ext4/ext4_common.c
@@ -854,16 +854,15 @@ fail:
 
 static int unlink_filename(char *filename, unsigned int blknr)
 {
-   int templength = 0;
-   int status, inodeno;
-   int found = 0;
+   int status;
+   int inodeno = 0;
int offset;
char *block_buffer = NULL;
struct ext2_dirent *dir = NULL;
-   struct ext2_dirent *previous_dir = NULL;
-   char *ptr = NULL;
+   struct ext2_dirent *previous_dir;
struct ext_filesystem *fs = get_fs();
int ret = -1;
+   char *direntname;
 
block_buffer = zalloc(fs->blksz);
if (!block_buffer)
@@ -877,20 +876,18 @@ static int unlink_filename(char *filename, unsigned int 
blknr)
 
if (ext4fs_log_journal(block_buffer, blknr))
goto fail;
-   dir = (struct ext2_dirent *)block_buffer;
-   ptr = (char *)dir;
offset = 0;
-   while (le16_to_cpu(dir->direntlen) >= 0) {
-   /*
-* blocksize-offset because last
-* directory length i.e., *dir->direntlen
-* is free availble space in the block that
-* means it is a last entry of directory entry
-*/
+   do {
+   previous_dir = dir;
+   dir = (struct ext2_dirent *)(block_buffer + offset);
+   direntname = (char *)(dir) + sizeof(struct ext2_dirent);
+
+   int direntlen = le16_to_cpu(dir->direntlen);
+   if (direntlen < sizeof(struct ext2_dirent))
+   break;
+
if (dir->inode && (strlen(filename) == dir->namelen) &&
-   (strncmp(ptr + sizeof(struct ext2_dirent),
-filename, dir->namelen) == 0)) {
-   printf("file found, deleting\n");
+   (strncmp(direntname, filename, dir->namelen) == 0)) {
inodeno = le32_to_cpu(dir->inode);
if (previous_dir) {
uint16_t new_len;
@@ -900,23 +897,15 @@ static int unlink_filename(char *filename, unsigned int 
blknr)
} else {
dir->inode = 0;
}
-   found = 1;
break;
}
 
-   if (fs->blksz - offset == le16_to_cpu(dir->direntlen))
-   break;
+   offset += direntlen;
 
-   /* traversing the each directory entry */
-   templength = le16_to_cpu(dir->direntlen);
-   offset = offset + templength;
-   previous_dir = dir;
-   dir = (struct ext2_dirent *)((char *)dir + templength);
-   ptr = (char *)dir;
-   }
+   } while (offset < fs->blksz);
 
+   if (inodeno > 0) {
 
-   if (found == 1) {
if (ext4fs_put_metadata(block_buffer, blknr))
goto fail;
ret = inodeno;
-- 
2.10.0

___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


[U-Boot] [PATCH 0/3] ext4: cleanup/fix unlink_filename function

2016-10-09 Thread Stefan Brüns
This patch series addresses Coverity defects CID 153383/153384.
The first patch is a preparation patch, the second addresses the
actual issue.
The last patch corrects the journal handling in the same function.

Stefan Brüns (3):
  ext4: cleanup unlink_filename function
  ext4: Fix handling of direntlen in unlink_filename
  ext4: Only write journal entries for modified blocks in
unlink_filename

 fs/ext4/ext4_common.c | 87 +++
 1 file changed, 40 insertions(+), 47 deletions(-)

-- 
2.10.0

___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


[U-Boot] [PATCH 3/3] ext4: Only write journal entries for modified blocks in unlink_filename

2016-10-09 Thread Stefan Brüns
Instead of creating a journal entry for each directory block, even
if the block is unmodified, only log the modified block.

Signed-off-by: Stefan Brüns <stefan.bru...@rwth-aachen.de>
---
 fs/ext4/ext4_common.c | 23 +--
 1 file changed, 13 insertions(+), 10 deletions(-)

diff --git a/fs/ext4/ext4_common.c b/fs/ext4/ext4_common.c
index 11be0b7..ec02eec 100644
--- a/fs/ext4/ext4_common.c
+++ b/fs/ext4/ext4_common.c
@@ -874,8 +874,6 @@ static int unlink_filename(char *filename, unsigned int 
blknr)
if (status == 0)
goto fail;
 
-   if (ext4fs_log_journal(block_buffer, blknr))
-   goto fail;
offset = 0;
do {
previous_dir = dir;
@@ -889,14 +887,6 @@ static int unlink_filename(char *filename, unsigned int 
blknr)
if (dir->inode && (strlen(filename) == dir->namelen) &&
(strncmp(direntname, filename, dir->namelen) == 0)) {
inodeno = le32_to_cpu(dir->inode);
-   if (previous_dir) {
-   uint16_t new_len;
-   new_len = le16_to_cpu(previous_dir->direntlen);
-   new_len += le16_to_cpu(dir->direntlen);
-   previous_dir->direntlen = cpu_to_le16(new_len);
-   } else {
-   dir->inode = 0;
-   }
break;
}
 
@@ -905,7 +895,20 @@ static int unlink_filename(char *filename, unsigned int 
blknr)
} while (offset < fs->blksz);
 
if (inodeno > 0) {
+   printf("file found, deleting\n");
+   if (ext4fs_log_journal(block_buffer, blknr))
+   goto fail;
 
+   if (previous_dir) {
+   /* merge dir entry with predecessor */
+   uint16_t new_len;
+   new_len = le16_to_cpu(previous_dir->direntlen);
+   new_len += le16_to_cpu(dir->direntlen);
+   previous_dir->direntlen = cpu_to_le16(new_len);
+   } else {
+   /* invalidate dir entry */
+   dir->inode = 0;
+   }
if (ext4fs_put_metadata(block_buffer, blknr))
goto fail;
ret = inodeno;
-- 
2.10.0

___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


[U-Boot] [PATCH v2 4/5] sandbox/fs: Set correct filetype for unknown filetype

2016-10-04 Thread Stefan Brüns
The "hostfs ls" command prefixes each directory entry with either DIR,
LNK or "   " if it is a directory, symlink resp. regular file, or
"???" for any other or unknown type.
The latter only works if the type is set correctly, as the entry defaults
to OS_FILET_REG and e.g. socket files show up as regular files.

Signed-off-by: Stefan Brüns <stefan.bru...@rwth-aachen.de>
Acked-by: Simon Glass <s...@chromium.org>
---
 arch/sandbox/cpu/os.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/sandbox/cpu/os.c b/arch/sandbox/cpu/os.c
index 16af3f5..df2bd4c 100644
--- a/arch/sandbox/cpu/os.c
+++ b/arch/sandbox/cpu/os.c
@@ -363,6 +363,8 @@ int os_dirent_ls(const char *dirname, struct os_dirent_node 
**headp)
case DT_LNK:
next->type = OS_FILET_LNK;
break;
+   default:
+   next->type = OS_FILET_UNKNOWN;
}
next->size = 0;
snprintf(fname, len, "%s/%s", dirname, next->name);
-- 
2.10.0

___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


[U-Boot] [PATCH v3 5/7] efi_loader: Readd freed pages to memory pool

2016-10-01 Thread Stefan Brüns
Currently each allocation creates a new mapping. Readding the mapping
as free memory (EFI_CONVENTIONAL_MEMORY) potentially allows to hand out
an existing mapping, thus limiting the number of mapping descriptors in
the memory map.

Mitigates a problem with current (4.8rc7) linux kernels when doing an
efi_get_memory map, resulting in an infinite loop. Space for the memory
map is reserved with allocate_pool (implicitly creating a new mapping) and
filled. If there is insufficient slack space (8 entries) in the map, the
space is freed and a new round is started, with space for one more entry.
As each round increases requirement and allocation by exactly one, there
is never enough slack space. (At least 32 entries are allocated, so as
long as there are less than 24 entries, there is enough slack).
Earlier kernels reserved no slack, and did less allocations, so this
problem was not visible.

Signed-off-by: Stefan Brüns <stefan.bru...@rwth-aachen.de>
Reviewed-by: Alexander Graf <ag...@suse.de>
---
 include/efi_loader.h|  2 +-
 lib/efi_loader/efi_memory.c | 11 +--
 2 files changed, 10 insertions(+), 3 deletions(-)

diff --git a/include/efi_loader.h b/include/efi_loader.h
index 341d4a4..6d64f4b 100644
--- a/include/efi_loader.h
+++ b/include/efi_loader.h
@@ -117,7 +117,7 @@ void *efi_alloc(uint64_t len, int memory_type);
 /* More specific EFI memory allocator, called by EFI payloads */
 efi_status_t efi_allocate_pages(int type, int memory_type, unsigned long pages,
uint64_t *memory);
-/* EFI memory free function. Not implemented today */
+/* EFI memory free function. */
 efi_status_t efi_free_pages(uint64_t memory, unsigned long pages);
 /* EFI memory allocator for small allocations, called by EFI payloads */
 efi_status_t efi_allocate_pool(int pool_type, unsigned long size,
diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c
index fa5c639..7051948 100644
--- a/lib/efi_loader/efi_memory.c
+++ b/lib/efi_loader/efi_memory.c
@@ -335,8 +335,15 @@ void *efi_alloc(uint64_t len, int memory_type)
 
 efi_status_t efi_free_pages(uint64_t memory, unsigned long pages)
 {
-   /* We don't free, let's cross our fingers we have plenty RAM */
-   return EFI_SUCCESS;
+   uint64_t r = 0;
+
+   r = efi_add_memory_map(memory, pages, EFI_CONVENTIONAL_MEMORY, false);
+   /* Merging of adjacent free regions is missing */
+
+   if (r == memory)
+   return EFI_SUCCESS;
+
+   return EFI_NOT_FOUND;
 }
 
 efi_status_t efi_allocate_pool(int pool_type, unsigned long size,
-- 
2.10.0

___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


[U-Boot] [PATCH v3 7/7] efi_loader: Do not leak memory when unlinking a mapping

2016-10-01 Thread Stefan Brüns
As soon as a mapping is unlinked from the list, there are no further
references to it, so it should be freed. If it not unlinked,
update the start address and length.

Signed-off-by: Stefan Brüns <stefan.bru...@rwth-aachen.de>
Reviewed-by: Alexander Graf <ag...@suse.de>
---
 lib/efi_loader/efi_memory.c | 7 +--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c
index 2bbf8eb..7e4ee01 100644
--- a/lib/efi_loader/efi_memory.c
+++ b/lib/efi_loader/efi_memory.c
@@ -115,10 +115,13 @@ static int efi_mem_carve_out(struct efi_mem_list *map,
if (map_end == carve_end) {
/* Full overlap, just remove map */
list_del(>link);
+   free(map);
+   } else {
+   map->desc.physical_start = carve_end;
+   map->desc.num_pages = (map_end - carve_end)
+ >> EFI_PAGE_SHIFT;
}
 
-   map_desc->physical_start = carve_end;
-   map_desc->num_pages = (map_end - carve_end) >> EFI_PAGE_SHIFT;
return (carve_end - carve_start) >> EFI_PAGE_SHIFT;
}
 
-- 
2.10.0

___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


[U-Boot] [PATCH v2 0/6] efi_loader: implement BS.FreePages()/BS.FreePool, some cleanup

2016-10-01 Thread Stefan Brüns
Linux 4.8 no longer boots, as it runs out of descriptor space. Readding
the mapping allows reuse, and the next AllocatePool will likely not add
a new mapping.

Also fix some small issues found while debugging.

v2, updated:
  efi_loader: Fix memory map size check to avoid out-of-bounds access
  - (Hopefully) clarified commit message
  efi_loader: Track size of pool allocations to allow freeing
  - rebased on top of 'efi_loader: Fix crash on 32-bit systems'
  - assert correct address in efi_free_pool
  - use EFI_PAGE_MASK instead of 0xfff, EFI_PAGE_SHIFT likewise

v3, added:
  efi_loader: Move efi_allocate_pool implementation to efi_memory.c
v3, updated:
  efi_loader: Fix memory map size check to avoid out-of-bounds access
  - set descriptor_size/_version even if EFI_BUFFER_TOO_SMALL
  efi_loader: Track size of pool allocations to allow freeing
  - use a struct instead of pointer arithmetic, add some comments

Stefan Brüns (7):
  efi_loader: Update description of internal efi_mem_carve_out
  efi_loader: Fix memory map size check to avoid out-of-bounds access
  efi_loader: Move efi_allocate_pool implementation to efi_memory.c
  efi_loader: Track size of pool allocations to allow freeing
  efi_loader: Readd freed pages to memory pool
  efi_loader: Keep memory mapping sorted when splitting an entry
  efi_loader: Do not leak memory when unlinking a mapping

 include/efi_loader.h  |  7 +++-
 lib/efi_loader/efi_boottime.c | 17 
 lib/efi_loader/efi_memory.c   | 92 +--
 3 files changed, 95 insertions(+), 21 deletions(-)

-- 
2.10.0

___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


[U-Boot] [PATCH v3 3/7] efi_loader: Move efi_allocate_pool implementation to efi_memory.c

2016-10-01 Thread Stefan Brüns
Implementation essentially unchanged, but use EFI_PAGE_MASK/SHIFT
instead of numeric constants.

Signed-off-by: Stefan Brüns <stefan.bru...@rwth-aachen.de>
---
 include/efi_loader.h  |  3 +++
 lib/efi_loader/efi_boottime.c | 11 +--
 lib/efi_loader/efi_memory.c   | 11 +++
 3 files changed, 19 insertions(+), 6 deletions(-)

diff --git a/include/efi_loader.h b/include/efi_loader.h
index 9738835..40e7beb 100644
--- a/include/efi_loader.h
+++ b/include/efi_loader.h
@@ -119,6 +119,9 @@ efi_status_t efi_allocate_pages(int type, int memory_type, 
unsigned long pages,
uint64_t *memory);
 /* EFI memory free function. Not implemented today */
 efi_status_t efi_free_pages(uint64_t memory, unsigned long pages);
+/* EFI memory allocator for small allocations, called by EFI payloads */
+efi_status_t efi_allocate_pool(int pool_type, unsigned long size,
+  void **buffer);
 /* Returns the EFI memory map */
 efi_status_t efi_get_memory_map(unsigned long *memory_map_size,
struct efi_mem_desc *memory_map,
diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
index 784891b..eb74cb0 100644
--- a/lib/efi_loader/efi_boottime.c
+++ b/lib/efi_loader/efi_boottime.c
@@ -130,15 +130,14 @@ efi_status_t EFIAPI efi_get_memory_map_ext(unsigned long 
*memory_map_size,
return EFI_EXIT(r);
 }
 
-static efi_status_t EFIAPI efi_allocate_pool(int pool_type, unsigned long size,
-void **buffer)
+static efi_status_t EFIAPI efi_allocate_pool_ext(int pool_type,
+unsigned long size,
+void **buffer)
 {
efi_status_t r;
-   efi_physical_addr_t t;
 
EFI_ENTRY("%d, %ld, %p", pool_type, size, buffer);
-   r = efi_allocate_pages(0, pool_type, (size + 0xfff) >> 12, );
-   *buffer = (void *)(uintptr_t)t;
+   r = efi_allocate_pool(pool_type, size, buffer);
return EFI_EXIT(r);
 }
 
@@ -736,7 +735,7 @@ static const struct efi_boot_services efi_boot_services = {
.allocate_pages = efi_allocate_pages_ext,
.free_pages = efi_free_pages_ext,
.get_memory_map = efi_get_memory_map_ext,
-   .allocate_pool = efi_allocate_pool,
+   .allocate_pool = efi_allocate_pool_ext,
.free_pool = efi_free_pool,
.create_event = efi_create_event,
.set_timer = efi_set_timer,
diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c
index 5d71fdf..045558d 100644
--- a/lib/efi_loader/efi_memory.c
+++ b/lib/efi_loader/efi_memory.c
@@ -327,6 +327,17 @@ efi_status_t efi_free_pages(uint64_t memory, unsigned long 
pages)
return EFI_SUCCESS;
 }
 
+efi_status_t efi_allocate_pool(int pool_type, unsigned long size,
+  void **buffer)
+{
+   efi_status_t r;
+   efi_physical_addr_t t;
+   u64 num_pages = (size + EFI_PAGE_MASK) >> EFI_PAGE_SHIFT;
+
+   r = efi_allocate_pages(0, pool_type, num_pages, );
+   return EFI_EXIT(r);
+}
+
 efi_status_t efi_get_memory_map(unsigned long *memory_map_size,
   struct efi_mem_desc *memory_map,
   unsigned long *map_key,
-- 
2.10.0

___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


[U-Boot] [PATCH v3 4/7] efi_loader: Track size of pool allocations to allow freeing

2016-10-01 Thread Stefan Brüns
allocate_pool has to return a buffer which is 8-byte aligned. Shift the
region returned by allocate_pages by 8 byte and store the size in the
headroom. The 8 byte overhead is neglegible, but provides the required
size when freeing the allocation later.

Signed-off-by: Stefan Brüns <stefan.bru...@rwth-aachen.de>
---
 include/efi_loader.h  |  2 ++
 lib/efi_loader/efi_boottime.c |  6 +++---
 lib/efi_loader/efi_memory.c   | 40 +++-
 3 files changed, 44 insertions(+), 4 deletions(-)

diff --git a/include/efi_loader.h b/include/efi_loader.h
index 40e7beb..341d4a4 100644
--- a/include/efi_loader.h
+++ b/include/efi_loader.h
@@ -122,6 +122,8 @@ efi_status_t efi_free_pages(uint64_t memory, unsigned long 
pages);
 /* EFI memory allocator for small allocations, called by EFI payloads */
 efi_status_t efi_allocate_pool(int pool_type, unsigned long size,
   void **buffer);
+/* EFI pool memory free function. */
+efi_status_t efi_free_pool(void *buffer);
 /* Returns the EFI memory map */
 efi_status_t efi_get_memory_map(unsigned long *memory_map_size,
struct efi_mem_desc *memory_map,
diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
index eb74cb0..8274d8e 100644
--- a/lib/efi_loader/efi_boottime.c
+++ b/lib/efi_loader/efi_boottime.c
@@ -141,12 +141,12 @@ static efi_status_t EFIAPI efi_allocate_pool_ext(int 
pool_type,
return EFI_EXIT(r);
 }
 
-static efi_status_t EFIAPI efi_free_pool(void *buffer)
+static efi_status_t EFIAPI efi_free_pool_ext(void *buffer)
 {
efi_status_t r;
 
EFI_ENTRY("%p", buffer);
-   r = efi_free_pages((ulong)buffer, 0);
+   r = efi_free_pool(buffer);
return EFI_EXIT(r);
 }
 
@@ -736,7 +736,7 @@ static const struct efi_boot_services efi_boot_services = {
.free_pages = efi_free_pages_ext,
.get_memory_map = efi_get_memory_map_ext,
.allocate_pool = efi_allocate_pool_ext,
-   .free_pool = efi_free_pool,
+   .free_pool = efi_free_pool_ext,
.create_event = efi_create_event,
.set_timer = efi_set_timer,
.wait_for_event = efi_wait_for_event,
diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c
index 045558d..fa5c639 100644
--- a/lib/efi_loader/efi_memory.c
+++ b/lib/efi_loader/efi_memory.c
@@ -34,6 +34,18 @@ void *efi_bounce_buffer;
 #endif
 
 /*
+ * U-Boot services each EFI AllocatePool request as a separate
+ * (multiple) page allocation.  We have to track the number of pages
+ * to be able to free the correct amount later.
+ * EFI requires 8 byte alignement for pool allocations, so it is
+ * possible to reserve some headroom and serve the remainder.
+ */
+struct efi_pool_allocation {
+   u64 num_pages;
+   char data[];
+};
+
+/*
  * Sorts the memory list from highest address to lowest address
  *
  * When allocating memory we should always start from the highest
@@ -332,9 +344,35 @@ efi_status_t efi_allocate_pool(int pool_type, unsigned 
long size,
 {
efi_status_t r;
efi_physical_addr_t t;
-   u64 num_pages = (size + EFI_PAGE_MASK) >> EFI_PAGE_SHIFT;
+   u64 num_pages = (size + sizeof(u64) + EFI_PAGE_MASK) >> EFI_PAGE_SHIFT;
+
+   if (size == 0) {
+   *buffer = NULL;
+   return EFI_EXIT(EFI_SUCCESS);
+   }
 
r = efi_allocate_pages(0, pool_type, num_pages, );
+
+   if (r == EFI_SUCCESS) {
+   struct efi_pool_allocation *alloc = (void *)(uintptr_t)t;
+   alloc->num_pages = num_pages;
+   *buffer = &(alloc->data);
+   assert(((uintptr_t)(*buffer) & 0x7) == 0);
+   }
+
+   return EFI_EXIT(r);
+}
+
+efi_status_t efi_free_pool(void *buffer)
+{
+   efi_status_t r;
+   struct efi_pool_allocation *alloc;
+
+   alloc = container_of(buffer, struct efi_pool_allocation, data);
+   assert(((uintptr_t)alloc & EFI_PAGE_MASK) == 0);
+
+   r = efi_free_pages((uintptr_t)alloc, alloc->num_pages);
+
return EFI_EXIT(r);
 }
 
-- 
2.10.0

___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


[U-Boot] [PATCH v3 1/7] efi_loader: Update description of internal efi_mem_carve_out

2016-10-01 Thread Stefan Brüns
In 74c16acce30bb882ad5951829d8dafef8eea564c the return values where
changed, but the description was kept.

Signed-off-by: Stefan Brüns <stefan.bru...@rwth-aachen.de>
---
 lib/efi_loader/efi_memory.c | 14 +++---
 1 file changed, 11 insertions(+), 3 deletions(-)

diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c
index 80e4e26..ebe8e94 100644
--- a/lib/efi_loader/efi_memory.c
+++ b/lib/efi_loader/efi_memory.c
@@ -62,9 +62,17 @@ static void efi_mem_sort(void)
  * Unmaps all memory occupied by the carve_desc region from the
  * list entry pointed to by map.
  *
- * Returns 1 if carving was performed or 0 if the regions don't overlap.
- * Returns -1 if it would affect non-RAM regions but overlap_only_ram is set.
- * Carving is only guaranteed to complete when all regions return 0.
+ * Returns EFI_CARVE_NO_OVERLAP if the regions don't overlap.
+ * Returns EFI_CARVE_OVERLAPS_NONRAM if the carve and map overlap,
+ *and the map contains anything but free ram.
+ *(only when overlap_only_ram is true)
+ * Returns EFI_CARVE_LOOP_AGAIN if the mapping list should be traversed
+ *again, as it has been altered
+ * Returns the number of overlapping pages. The pages are removed from
+ * the mapping list.
+ *
+ * In case of EFI_CARVE_OVERLAPS_NONRAM it is the callers responsibility
+ * to readd the already carved out pages to the mapping.
  */
 static int efi_mem_carve_out(struct efi_mem_list *map,
 struct efi_mem_desc *carve_desc,
-- 
2.10.0

___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


[U-Boot] [PATCH v3 6/7] efi_loader: Keep memory mapping sorted when splitting an entry

2016-10-01 Thread Stefan Brüns
The code assumes sorted mappings in descending address order. When
splitting a mapping, insert the new part next to the current mapping.

Signed-off-by: Stefan Brüns <stefan.bru...@rwth-aachen.de>
Reviewed-by: Alexander Graf <ag...@suse.de>
---
 lib/efi_loader/efi_memory.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c
index 7051948..2bbf8eb 100644
--- a/lib/efi_loader/efi_memory.c
+++ b/lib/efi_loader/efi_memory.c
@@ -134,7 +134,8 @@ static int efi_mem_carve_out(struct efi_mem_list *map,
newmap->desc = map->desc;
newmap->desc.physical_start = carve_start;
newmap->desc.num_pages = (map_end - carve_start) >> EFI_PAGE_SHIFT;
-list_add_tail(>link, _mem);
+   /* Insert before current entry (descending address order) */
+   list_add_tail(>link, >link);
 
/* Shrink the map to [ map_start ... carve_start ] */
map_desc->num_pages = (carve_start - map_start) >> EFI_PAGE_SHIFT;
-- 
2.10.0

___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


[U-Boot] [PATCH v3 2/7] efi_loader: Fix memory map size check to avoid out-of-bounds access

2016-10-01 Thread Stefan Brüns
Do not overwrite the specified size of the provided buffer without
having checked it is sufficient.

If the buffer is to small, memory_map_size is updated to indicate the
required size, and an error code is returned.

Signed-off-by: Stefan Brüns <stefan.bru...@rwth-aachen.de>
---
 lib/efi_loader/efi_memory.c | 8 +---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c
index ebe8e94..5d71fdf 100644
--- a/lib/efi_loader/efi_memory.c
+++ b/lib/efi_loader/efi_memory.c
@@ -342,16 +342,18 @@ efi_status_t efi_get_memory_map(unsigned long 
*memory_map_size,
 
map_size = map_entries * sizeof(struct efi_mem_desc);
 
-   *memory_map_size = map_size;
-
if (descriptor_size)
*descriptor_size = sizeof(struct efi_mem_desc);
 
if (descriptor_version)
*descriptor_version = EFI_MEMORY_DESCRIPTOR_VERSION;
 
-   if (*memory_map_size < map_size)
+   if (*memory_map_size < map_size) {
+   *memory_map_size = map_size;
return EFI_BUFFER_TOO_SMALL;
+   }
+
+   *memory_map_size = map_size;
 
/* Copy list into array */
if (memory_map) {
-- 
2.10.0

___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


[U-Boot] [PATCH 4/5] sandbox/fs: Set correct filetype for unknown filetype

2016-10-01 Thread Stefan Brüns
Signed-off-by: Stefan Brüns <stefan.bru...@rwth-aachen.de>
---
 arch/sandbox/cpu/os.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/sandbox/cpu/os.c b/arch/sandbox/cpu/os.c
index 16af3f5..df2bd4c 100644
--- a/arch/sandbox/cpu/os.c
+++ b/arch/sandbox/cpu/os.c
@@ -363,6 +363,8 @@ int os_dirent_ls(const char *dirname, struct os_dirent_node 
**headp)
case DT_LNK:
next->type = OS_FILET_LNK;
break;
+   default:
+   next->type = OS_FILET_UNKNOWN;
}
next->size = 0;
snprintf(fname, len, "%s/%s", dirname, next->name);
-- 
2.10.0

___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


[U-Boot] [PATCH 5/5] sandbox/fs: Use readdir instead of deprecated readdir_r

2016-10-01 Thread Stefan Brüns
Using readdir_r limits the maximum file name length and may even be
unsafe, and is thus deprecated in since glibc 2.24.

Signed-off-by: Stefan Brüns <stefan.bru...@rwth-aachen.de>
---
 arch/sandbox/cpu/os.c | 19 +++
 1 file changed, 11 insertions(+), 8 deletions(-)

diff --git a/arch/sandbox/cpu/os.c b/arch/sandbox/cpu/os.c
index df2bd4c..35ea00c 100644
--- a/arch/sandbox/cpu/os.c
+++ b/arch/sandbox/cpu/os.c
@@ -313,7 +313,7 @@ void os_dirent_free(struct os_dirent_node *node)
 
 int os_dirent_ls(const char *dirname, struct os_dirent_node **headp)
 {
-   struct dirent entry, *result;
+   struct dirent *entry;
struct os_dirent_node *head, *node, *next;
struct stat buf;
DIR *dir;
@@ -337,12 +337,15 @@ int os_dirent_ls(const char *dirname, struct 
os_dirent_node **headp)
}
 
for (node = head = NULL;; node = next) {
-   ret = readdir_r(dir, , );
-   if (ret || !result)
+   errno = 0;
+   entry = readdir(dir);
+   if (!entry) {
+   ret = errno;
break;
-   next = malloc(sizeof(*node) + strlen(entry.d_name) + 1);
-   if (dirlen + strlen(entry.d_name) > len) {
-   len = dirlen + strlen(entry.d_name);
+   }
+   next = malloc(sizeof(*node) + strlen(entry->d_name) + 1);
+   if (dirlen + strlen(entry->d_name) > len) {
+   len = dirlen + strlen(entry->d_name);
fname = realloc(fname, len);
}
if (!next || !fname) {
@@ -352,8 +355,8 @@ int os_dirent_ls(const char *dirname, struct os_dirent_node 
**headp)
goto done;
}
next->next = NULL;
-   strcpy(next->name, entry.d_name);
-   switch (entry.d_type) {
+   strcpy(next->name, entry->d_name);
+   switch (entry->d_type) {
case DT_REG:
next->type = OS_FILET_REG;
break;
-- 
2.10.0

___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


[U-Boot] [PATCH 0/5] Fix some trivial issues in sandbox/fs

2016-10-01 Thread Stefan Brüns
Stefan Brüns (5):
  sandbox/fs: Free memory allocated by os_dirent_ls
  sandbox/fs: Make linking of nodes in os_dirent_ls more obvious
  sandbox/fs: Use correct size path name buffer
  sandbox/fs: Set correct filetype for unknown filetype
  sandbox/fs: Use readdir instead of deprecated readdir_r

 arch/sandbox/cpu/os.c  | 34 +++---
 fs/sandbox/sandboxfs.c |  1 +
 include/os.h   | 11 ++-
 3 files changed, 34 insertions(+), 12 deletions(-)

-- 
2.10.0

___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


[U-Boot] [PATCH 3/5] sandbox/fs: Use correct size path name buffer

2016-10-01 Thread Stefan Brüns
The readdir linux manpage explicitly states (quoting POSIX.1) that
sizeof(d_name) is not correct for determining the required size, but to
always use strlen. Grow the buffer if needed.

Signed-off-by: Stefan Brüns <stefan.bru...@rwth-aachen.de>
---
 arch/sandbox/cpu/os.c | 13 ++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/arch/sandbox/cpu/os.c b/arch/sandbox/cpu/os.c
index c71882a..16af3f5 100644
--- a/arch/sandbox/cpu/os.c
+++ b/arch/sandbox/cpu/os.c
@@ -320,14 +320,16 @@ int os_dirent_ls(const char *dirname, struct 
os_dirent_node **headp)
int ret;
char *fname;
int len;
+   int dirlen;
 
*headp = NULL;
dir = opendir(dirname);
if (!dir)
return -1;
 
-   /* Create a buffer for the maximum filename length */
-   len = sizeof(entry.d_name) + strlen(dirname) + 2;
+   /* Create a buffer upfront, with typically sufficient size */
+   dirlen = strlen(dirname) + 2;
+   len = dirlen + 256;
fname = malloc(len);
if (!fname) {
ret = -ENOMEM;
@@ -339,7 +341,12 @@ int os_dirent_ls(const char *dirname, struct 
os_dirent_node **headp)
if (ret || !result)
break;
next = malloc(sizeof(*node) + strlen(entry.d_name) + 1);
-   if (!next) {
+   if (dirlen + strlen(entry.d_name) > len) {
+   len = dirlen + strlen(entry.d_name);
+   fname = realloc(fname, len);
+   }
+   if (!next || !fname) {
+   free(next);
os_dirent_free(head);
ret = -ENOMEM;
goto done;
-- 
2.10.0

___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


[U-Boot] [PATCH 2/5] sandbox/fs: Make linking of nodes in os_dirent_ls more obvious

2016-10-01 Thread Stefan Brüns
Previously, after reading/creating the second dirent, the second entry
would be chained to the first entry and the first entry would be linked
to head. Instead, immediately link the first entry to head.

Signed-off-by: Stefan Brüns <stefan.bru...@rwth-aachen.de>
---
 arch/sandbox/cpu/os.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/sandbox/cpu/os.c b/arch/sandbox/cpu/os.c
index 2d63dd8..c71882a 100644
--- a/arch/sandbox/cpu/os.c
+++ b/arch/sandbox/cpu/os.c
@@ -363,8 +363,8 @@ int os_dirent_ls(const char *dirname, struct os_dirent_node 
**headp)
next->size = buf.st_size;
if (node)
node->next = next;
-   if (!head)
-   head = node;
+   else
+   head = next;
}
*headp = head;
 
-- 
2.10.0

___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


[U-Boot] [PATCH 1/5] sandbox/fs: Free memory allocated by os_dirent_ls

2016-10-01 Thread Stefan Brüns
Signed-off-by: Stefan Brüns <stefan.bru...@rwth-aachen.de>
---
 fs/sandbox/sandboxfs.c |  1 +
 include/os.h   | 11 ++-
 2 files changed, 11 insertions(+), 1 deletion(-)

diff --git a/fs/sandbox/sandboxfs.c b/fs/sandbox/sandboxfs.c
index 2703eed..cd10fd6 100644
--- a/fs/sandbox/sandboxfs.c
+++ b/fs/sandbox/sandboxfs.c
@@ -94,6 +94,7 @@ int sandbox_fs_ls(const char *dirname)
printf("%s %10lu %s\n", os_dirent_get_typename(node->type),
   node->size, node->name);
}
+   os_dirent_free(head);
 
return 0;
 }
diff --git a/include/os.h b/include/os.h
index 1782e50..049b248 100644
--- a/include/os.h
+++ b/include/os.h
@@ -215,9 +215,18 @@ struct os_dirent_node {
 int os_dirent_ls(const char *dirname, struct os_dirent_node **headp);
 
 /**
+ * Free directory list
+ *
+ * This frees a linked list containing a directory listing.
+ *
+ * @param node Pointer to head of linked list
+ */
+void os_dirent_free(struct os_dirent_node *node);
+
+/**
  * Get the name of a directory entry type
  *
- * @param type Type to cehck
+ * @param type Type to check
  * @return string containing the name of that type, or "???" if none/invalid
  */
 const char *os_dirent_get_typename(enum os_dirent_t type);
-- 
2.10.0

___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


[U-Boot] [PATCH v2 5/6] efi_loader: Keep memory mapping sorted when splitting an entry

2016-10-01 Thread Stefan Brüns
The code assumes sorted mappings in descending address order. When
splitting a mapping, insert the new part next to the current mapping.

Signed-off-by: Stefan Brüns <stefan.bru...@rwth-aachen.de>
Reviewed-by: Alexander Graf <ag...@suse.de>
---
 lib/efi_loader/efi_memory.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c
index 9c785dd..26a5d50 100644
--- a/lib/efi_loader/efi_memory.c
+++ b/lib/efi_loader/efi_memory.c
@@ -122,7 +122,8 @@ static int efi_mem_carve_out(struct efi_mem_list *map,
newmap->desc = map->desc;
newmap->desc.physical_start = carve_start;
newmap->desc.num_pages = (map_end - carve_start) >> EFI_PAGE_SHIFT;
-list_add_tail(>link, _mem);
+   /* Insert before current entry (descending address order) */
+   list_add_tail(>link, >link);
 
/* Shrink the map to [ map_start ... carve_start ] */
map_desc->num_pages = (carve_start - map_start) >> EFI_PAGE_SHIFT;
-- 
2.10.0

___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


[U-Boot] [PATCH v2 3/6] efi_loader: Track size of pool allocations to allow freeing

2016-10-01 Thread Stefan Brüns
allocate_pool has to return a buffer which is 8-byte aligned. Shift the
region returned by allocate_pages by 8 byte and store the size in the
headroom. The 8 byte overhead is neglegible, but provides the required
size when freeing the allocation later.

Signed-off-by: Stefan Brüns <stefan.bru...@rwth-aachen.de>
---
 lib/efi_loader/efi_boottime.c | 24 +---
 1 file changed, 21 insertions(+), 3 deletions(-)

diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
index 784891b..c413ecb 100644
--- a/lib/efi_loader/efi_boottime.c
+++ b/lib/efi_loader/efi_boottime.c
@@ -135,19 +135,37 @@ static efi_status_t EFIAPI efi_allocate_pool(int 
pool_type, unsigned long size,
 {
efi_status_t r;
efi_physical_addr_t t;
+   u64 num_pages = (size + 8 + EFI_PAGE_MASK) >> EFI_PAGE_SHIFT;
 
EFI_ENTRY("%d, %ld, %p", pool_type, size, buffer);
-   r = efi_allocate_pages(0, pool_type, (size + 0xfff) >> 12, );
-   *buffer = (void *)(uintptr_t)t;
+
+   if (size == 0) {
+   *buffer = NULL;
+   return EFI_EXIT(EFI_SUCCESS);
+   }
+
+   r = efi_allocate_pages(0, pool_type, num_pages, );
+
+   if (r == EFI_SUCCESS) {
+   *(u64 *)(uintptr_t)t = num_pages;
+   *buffer = (void *)(uintptr_t)(t + 8);
+   }
+
return EFI_EXIT(r);
 }
 
 static efi_status_t EFIAPI efi_free_pool(void *buffer)
 {
efi_status_t r;
+   u64 num_pages;
 
EFI_ENTRY("%p", buffer);
-   r = efi_free_pages((ulong)buffer, 0);
+
+   buffer = (char *)(buffer) - 8;
+   assert(((ulong)buffer & EFI_PAGE_MASK) == 0);
+   num_pages = *(u64 *)buffer;
+
+   r = efi_free_pages((ulong)buffer, num_pages);
return EFI_EXIT(r);
 }
 
-- 
2.10.0

___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


[U-Boot] [PATCH v2 1/6] efi_loader: Update description of internal efi_mem_carve_out

2016-10-01 Thread Stefan Brüns
In 74c16acce30bb882ad5951829d8dafef8eea564c the return values where
changed, but the description was kept.

Signed-off-by: Stefan Brüns <stefan.bru...@rwth-aachen.de>
---
 lib/efi_loader/efi_memory.c | 14 +++---
 1 file changed, 11 insertions(+), 3 deletions(-)

diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c
index 80e4e26..ebe8e94 100644
--- a/lib/efi_loader/efi_memory.c
+++ b/lib/efi_loader/efi_memory.c
@@ -62,9 +62,17 @@ static void efi_mem_sort(void)
  * Unmaps all memory occupied by the carve_desc region from the
  * list entry pointed to by map.
  *
- * Returns 1 if carving was performed or 0 if the regions don't overlap.
- * Returns -1 if it would affect non-RAM regions but overlap_only_ram is set.
- * Carving is only guaranteed to complete when all regions return 0.
+ * Returns EFI_CARVE_NO_OVERLAP if the regions don't overlap.
+ * Returns EFI_CARVE_OVERLAPS_NONRAM if the carve and map overlap,
+ *and the map contains anything but free ram.
+ *(only when overlap_only_ram is true)
+ * Returns EFI_CARVE_LOOP_AGAIN if the mapping list should be traversed
+ *again, as it has been altered
+ * Returns the number of overlapping pages. The pages are removed from
+ * the mapping list.
+ *
+ * In case of EFI_CARVE_OVERLAPS_NONRAM it is the callers responsibility
+ * to readd the already carved out pages to the mapping.
  */
 static int efi_mem_carve_out(struct efi_mem_list *map,
 struct efi_mem_desc *carve_desc,
-- 
2.10.0

___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


[U-Boot] [PATCH v2 2/6] efi_loader: Fix memory map size check to avoid out-of-bounds access

2016-10-01 Thread Stefan Brüns
Do not overwrite the specified size of the provided buffer without
having checked it is sufficient.

If the buffer is to small, memory_map_size is updated to indicate the
required size, and an error code is returned.

Signed-off-by: Stefan Brüns <stefan.bru...@rwth-aachen.de>
---
 lib/efi_loader/efi_memory.c | 8 +---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c
index ebe8e94..72a5870 100644
--- a/lib/efi_loader/efi_memory.c
+++ b/lib/efi_loader/efi_memory.c
@@ -342,6 +342,11 @@ efi_status_t efi_get_memory_map(unsigned long 
*memory_map_size,
 
map_size = map_entries * sizeof(struct efi_mem_desc);
 
+   if (*memory_map_size < map_size) {
+   *memory_map_size = map_size;
+   return EFI_BUFFER_TOO_SMALL;
+   }
+
*memory_map_size = map_size;
 
if (descriptor_size)
@@ -350,9 +355,6 @@ efi_status_t efi_get_memory_map(unsigned long 
*memory_map_size,
if (descriptor_version)
*descriptor_version = EFI_MEMORY_DESCRIPTOR_VERSION;
 
-   if (*memory_map_size < map_size)
-   return EFI_BUFFER_TOO_SMALL;
-
/* Copy list into array */
if (memory_map) {
/* Return the list in ascending order */
-- 
2.10.0

___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


[U-Boot] [PATCH v2 4/6] efi_loader: Readd freed pages to memory pool

2016-10-01 Thread Stefan Brüns
Currently each allocation creates a new mapping. Readding the mapping
as free memory (EFI_CONVENTIONAL_MEMORY) potentially allows to hand out
an existing mapping, thus limiting the number of mapping descriptors in
the memory map.

Mitigates a problem with current (4.8rc7) linux kernels when doing an
efi_get_memory map, resulting in an infinite loop. Space for the memory
map is reserved with allocate_pool (implicitly creating a new mapping) and
filled. If there is insufficient slack space (8 entries) in the map, the
space is freed and a new round is started, with space for one more entry.
As each round increases requirement and allocation by exactly one, there
is never enough slack space. (At least 32 entries are allocated, so as
long as there are less than 24 entries, there is enough slack).
Earlier kernels reserved no slack, and did less allocations, so this
problem was not visible.

Signed-off-by: Stefan Brüns <stefan.bru...@rwth-aachen.de>
Reviewed-by: Alexander Graf <ag...@suse.de>
---
 lib/efi_loader/efi_memory.c | 11 +--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c
index 72a5870..9c785dd 100644
--- a/lib/efi_loader/efi_memory.c
+++ b/lib/efi_loader/efi_memory.c
@@ -323,8 +323,15 @@ void *efi_alloc(uint64_t len, int memory_type)
 
 efi_status_t efi_free_pages(uint64_t memory, unsigned long pages)
 {
-   /* We don't free, let's cross our fingers we have plenty RAM */
-   return EFI_SUCCESS;
+   uint64_t r = 0;
+
+   r = efi_add_memory_map(memory, pages, EFI_CONVENTIONAL_MEMORY, false);
+   /* Merging of adjacent free regions is missing */
+
+   if (r == memory)
+   return EFI_SUCCESS;
+
+   return EFI_NOT_FOUND;
 }
 
 efi_status_t efi_get_memory_map(unsigned long *memory_map_size,
-- 
2.10.0

___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


[U-Boot] [PATCH v2 6/6] efi_loader: Do not leak memory when unlinking a mapping

2016-10-01 Thread Stefan Brüns
As soon as a mapping is unlinked from the list, there are no further
references to it, so it should be freed. If it not unlinked,
update the start address and length.

Signed-off-by: Stefan Brüns <stefan.bru...@rwth-aachen.de>
Reviewed-by: Alexander Graf <ag...@suse.de>
---
 lib/efi_loader/efi_memory.c | 7 +--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c
index 26a5d50..000e776 100644
--- a/lib/efi_loader/efi_memory.c
+++ b/lib/efi_loader/efi_memory.c
@@ -103,10 +103,13 @@ static int efi_mem_carve_out(struct efi_mem_list *map,
if (map_end == carve_end) {
/* Full overlap, just remove map */
list_del(>link);
+   free(map);
+   } else {
+   map->desc.physical_start = carve_end;
+   map->desc.num_pages = (map_end - carve_end)
+ >> EFI_PAGE_SHIFT;
}
 
-   map_desc->physical_start = carve_end;
-   map_desc->num_pages = (map_end - carve_end) >> EFI_PAGE_SHIFT;
return (carve_end - carve_start) >> EFI_PAGE_SHIFT;
}
 
-- 
2.10.0

___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


[U-Boot] [PATCH v2 0/6] efi_loader: implement BS.FreePages()/BS.FreePool, some cleanup

2016-10-01 Thread Stefan Brüns
Linux 4.8 no longer boots, as it runs out of descriptor space. Readding
the mapping allows reuse, and the next AllocatePool will likely not add
a new mapping.

Also fix some small issues found while debugging.

v2, updated:
  efi_loader: Fix memory map size check to avoid out-of-bounds access
  - (Hopefully) clarified commit message
  efi_loader: Track size of pool allocations to allow freeing
  - rebased on top of 'efi_loader: Fix crash on 32-bit systems'
  - assert correct address in efi_free_pool
  - use EFI_PAGE_MASK instead of 0xfff, EFI_PAGE_SHIFT likewise

Stefan Brüns (6):
  efi_loader: Update description of internal efi_mem_carve_out
  efi_loader: Fix memory map size check to avoid out-of-bounds access
  efi_loader: Track size of pool allocations to allow freeing
  efi_loader: Readd freed pages to memory pool
  efi_loader: Keep memory mapping sorted when splitting an entry
  efi_loader: Do not leak memory when unlinking a mapping

 lib/efi_loader/efi_boottime.c | 24 +---
 lib/efi_loader/efi_memory.c   | 43 ---
 2 files changed, 53 insertions(+), 14 deletions(-)

-- 
2.10.0

___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


[U-Boot] [PATCH 6/6] efi_loader: Do not leak memory when unlinking a mapping

2016-09-29 Thread Stefan Brüns
As soon as a mapping is unlinked from the list, there are no further
references to it, so it should be freed. If it not unlinked,
update the start address and length.

Signed-off-by: Stefan Brüns <stefan.bru...@rwth-aachen.de>
---
 lib/efi_loader/efi_memory.c | 7 +--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c
index 0fcfb7a..6d8fae4 100644
--- a/lib/efi_loader/efi_memory.c
+++ b/lib/efi_loader/efi_memory.c
@@ -103,10 +103,13 @@ static int efi_mem_carve_out(struct efi_mem_list *map,
if (map_end == carve_end) {
/* Full overlap, just remove map */
list_del(>link);
+   free(map);
+   } else {
+   map->desc.physical_start = carve_end;
+   map->desc.num_pages = (map_end - carve_end)
+ >> EFI_PAGE_SHIFT;
}
 
-   map_desc->physical_start = carve_end;
-   map_desc->num_pages = (map_end - carve_end) >> EFI_PAGE_SHIFT;
return (carve_end - carve_start) >> EFI_PAGE_SHIFT;
}
 
-- 
2.10.0

___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


[U-Boot] [PATCH 2/6] efi_loader: Fix memory map size check to avoid out-of-bounds access

2016-09-29 Thread Stefan Brüns
memory_map_size as IN parameter specifies the size of the provided buffer.
If the buffer is to small, memory_map_size is updated to indicate the
required size, and an error code is returned.

Signed-off-by: Stefan Brüns <stefan.bru...@rwth-aachen.de>
---
 lib/efi_loader/efi_memory.c | 8 +---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c
index ebe8e94..5d71fdf 100644
--- a/lib/efi_loader/efi_memory.c
+++ b/lib/efi_loader/efi_memory.c
@@ -342,16 +342,18 @@ efi_status_t efi_get_memory_map(unsigned long 
*memory_map_size,
 
map_size = map_entries * sizeof(struct efi_mem_desc);
 
-   *memory_map_size = map_size;
-
if (descriptor_size)
*descriptor_size = sizeof(struct efi_mem_desc);
 
if (descriptor_version)
*descriptor_version = EFI_MEMORY_DESCRIPTOR_VERSION;
 
-   if (*memory_map_size < map_size)
+   if (*memory_map_size < map_size) {
+   *memory_map_size = map_size;
return EFI_BUFFER_TOO_SMALL;
+   }
+
+   *memory_map_size = map_size;
 
/* Copy list into array */
if (memory_map) {
-- 
2.10.0

___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


[U-Boot] [PATCH 1/6] efi_loader: Update description of internal efi_mem_carve_out

2016-09-29 Thread Stefan Brüns
In 74c16acce30bb882ad5951829d8dafef8eea564c the return values where
changed, but the description was kept.

Signed-off-by: Stefan Brüns <stefan.bru...@rwth-aachen.de>
---
 lib/efi_loader/efi_memory.c | 14 +++---
 1 file changed, 11 insertions(+), 3 deletions(-)

diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c
index 80e4e26..ebe8e94 100644
--- a/lib/efi_loader/efi_memory.c
+++ b/lib/efi_loader/efi_memory.c
@@ -62,9 +62,17 @@ static void efi_mem_sort(void)
  * Unmaps all memory occupied by the carve_desc region from the
  * list entry pointed to by map.
  *
- * Returns 1 if carving was performed or 0 if the regions don't overlap.
- * Returns -1 if it would affect non-RAM regions but overlap_only_ram is set.
- * Carving is only guaranteed to complete when all regions return 0.
+ * Returns EFI_CARVE_NO_OVERLAP if the regions don't overlap.
+ * Returns EFI_CARVE_OVERLAPS_NONRAM if the carve and map overlap,
+ *and the map contains anything but free ram.
+ *(only when overlap_only_ram is true)
+ * Returns EFI_CARVE_LOOP_AGAIN if the mapping list should be traversed
+ *again, as it has been altered
+ * Returns the number of overlapping pages. The pages are removed from
+ * the mapping list.
+ *
+ * In case of EFI_CARVE_OVERLAPS_NONRAM it is the callers responsibility
+ * to readd the already carved out pages to the mapping.
  */
 static int efi_mem_carve_out(struct efi_mem_list *map,
 struct efi_mem_desc *carve_desc,
-- 
2.10.0

___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


[U-Boot] [PATCH 5/6] efi_loader: Keep memory mapping sorted when splitting an entry

2016-09-29 Thread Stefan Brüns
The code assumes sorted mappings in descending address order. When
splitting a mapping, insert the new part next to the current mapping.

Signed-off-by: Stefan Brüns <stefan.bru...@rwth-aachen.de>
---
 lib/efi_loader/efi_memory.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c
index 763b79f..0fcfb7a 100644
--- a/lib/efi_loader/efi_memory.c
+++ b/lib/efi_loader/efi_memory.c
@@ -122,7 +122,8 @@ static int efi_mem_carve_out(struct efi_mem_list *map,
newmap->desc = map->desc;
newmap->desc.physical_start = carve_start;
newmap->desc.num_pages = (map_end - carve_start) >> EFI_PAGE_SHIFT;
-list_add_tail(>link, _mem);
+   /* Insert before current entry (descending address order) */
+   list_add_tail(>link, >link);
 
/* Shrink the map to [ map_start ... carve_start ] */
map_desc->num_pages = (carve_start - map_start) >> EFI_PAGE_SHIFT;
-- 
2.10.0

___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


[U-Boot] [PATCH 0/6] efi_loader: implement BS.FreePages()/BS.FreePool, some cleanup

2016-09-29 Thread Stefan Brüns
Linux 4.8 no longer boots, as it runs out of descriptor space. Readding
the mapping allows reuse, and the next AllocatePool will likely not add
a new mapping.

Also fix some small issues found while debugging.

Stefan Brüns (6):
  efi_loader: Update description of internal efi_mem_carve_out
  efi_loader: Fix memory map size check to avoid out-of-bounds access
  efi_loader: Track size of pool allocations to allow freeing
  efi_loader: Readd freed pages to memory pool
  efi_loader: Keep memory mapping sorted when splitting an entry
  efi_loader: Do not leak memory when unlinking a mapping

 lib/efi_loader/efi_boottime.c | 21 +++--
 lib/efi_loader/efi_memory.c   | 43 ---
 2 files changed, 51 insertions(+), 13 deletions(-)

-- 
2.10.0

___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


[U-Boot] [PATCH 3/6] efi_loader: Track size of pool allocations to allow freeing

2016-09-29 Thread Stefan Brüns
allocate_pool has to return a buffer which is 8-byte aligned. Shift the
region returned by allocate_pages by 8 byte and store the size in the
headroom. The 8 byte overhead is neglegible, but provides the required
size when freeing the allocation later.

Signed-off-by: Stefan Brüns <stefan.bru...@rwth-aachen.de>
---
 lib/efi_loader/efi_boottime.c | 21 +++--
 1 file changed, 19 insertions(+), 2 deletions(-)

diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
index be6f5e8..3e526eb 100644
--- a/lib/efi_loader/efi_boottime.c
+++ b/lib/efi_loader/efi_boottime.c
@@ -134,18 +134,35 @@ static efi_status_t EFIAPI efi_allocate_pool(int 
pool_type, unsigned long size,
 void **buffer)
 {
efi_status_t r;
+   u64 num_pages = (size + 8 + 0xfff) >> 12;
 
EFI_ENTRY("%d, %ld, %p", pool_type, size, buffer);
-   r = efi_allocate_pages(0, pool_type, (size + 0xfff) >> 12, 
(void*)buffer);
+
+   if (size == 0) {
+   *buffer = NULL;
+   return EFI_EXIT(EFI_SUCCESS);
+   }
+
+   r = efi_allocate_pages(0, pool_type, num_pages, (void *)buffer);
+   if (r == EFI_SUCCESS) {
+   *(u64 *)(*buffer) = num_pages;
+   *buffer = (char *)(*buffer) + 8;
+   }
+
return EFI_EXIT(r);
 }
 
 static efi_status_t EFIAPI efi_free_pool(void *buffer)
 {
efi_status_t r;
+   u64 num_pages;
 
EFI_ENTRY("%p", buffer);
-   r = efi_free_pages((ulong)buffer, 0);
+
+   buffer = (char *)(buffer) - 8;
+   num_pages = *(u64 *)buffer;
+
+   r = efi_free_pages((ulong)buffer, num_pages);
return EFI_EXIT(r);
 }
 
-- 
2.10.0

___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


[U-Boot] [PATCH 4/6] efi_loader: Readd freed pages to memory pool

2016-09-29 Thread Stefan Brüns
Currently each allocation creates a new mapping. Readding the mapping
as free memory (EFI_CONVENTIONAL_MEMORY) potentially allows to hand out
an existing mapping, thus limiting the number of mapping descriptors in
the memory map.

Mitigates a problem with current (4.8rc7) linux kernels when doing an
efi_get_memory map, resulting in an infinite loop. Space for the memory
map is reserved with allocate_pool (implicitly creating a new mapping) and
filled. If there is insufficient slack space (8 entries) in the map, the
space is freed and a new round is started, with space for one more entry.
As each round increases requirement and allocation by exactly one, there
is never enough slack space. (At least 32 entries are allocated, so as
long as there are less than 24 entries, there is enough slack).
Earlier kernels reserved no slack, and did less allocations, so this
problem was not visible.

Signed-off-by: Stefan Brüns <stefan.bru...@rwth-aachen.de>
---
 lib/efi_loader/efi_memory.c | 11 +--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c
index 5d71fdf..763b79f 100644
--- a/lib/efi_loader/efi_memory.c
+++ b/lib/efi_loader/efi_memory.c
@@ -323,8 +323,15 @@ void *efi_alloc(uint64_t len, int memory_type)
 
 efi_status_t efi_free_pages(uint64_t memory, unsigned long pages)
 {
-   /* We don't free, let's cross our fingers we have plenty RAM */
-   return EFI_SUCCESS;
+   uint64_t r = 0;
+
+   r = efi_add_memory_map(memory, pages, EFI_CONVENTIONAL_MEMORY, false);
+   /* Merging of adjacent free regions is missing */
+
+   if (r == memory)
+   return EFI_SUCCESS;
+
+   return EFI_NOT_FOUND;
 }
 
 efi_status_t efi_get_memory_map(unsigned long *memory_map_size,
-- 
2.10.0

___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


[U-Boot] [PATCH v2 6/7] ext4: Respect group descriptor size when adjusting free counts

2016-09-19 Thread Stefan Brüns
Also adjust high 16/32 bits when free inode/block counts are modified.

Signed-off-by: Stefan Brüns <stefan.bru...@rwth-aachen.de>
---
v2: rebase on last version of ext4 endian fixes

 fs/ext4/ext4_common.c | 53 +++
 fs/ext4/ext4_write.c  | 40 ++
 2 files changed, 69 insertions(+), 24 deletions(-)

diff --git a/fs/ext4/ext4_common.c b/fs/ext4/ext4_common.c
index 90e7602..1336068 100644
--- a/fs/ext4/ext4_common.c
+++ b/fs/ext4/ext4_common.c
@@ -60,22 +60,51 @@ static inline void ext4fs_sb_free_inodes_dec(struct 
ext2_sblock *sb)
 
 static inline void ext4fs_sb_free_blocks_dec(struct ext2_sblock *sb)
 {
-   sb->free_blocks = cpu_to_le32(le32_to_cpu(sb->free_blocks) - 1);
+   uint64_t free_blocks = le32_to_cpu(sb->free_blocks);
+   free_blocks += (uint64_t)le32_to_cpu(sb->free_blocks_high) << 32;
+   free_blocks--;
+
+   sb->free_blocks = cpu_to_le32(free_blocks & 0x);
+   sb->free_blocks_high = cpu_to_le16(free_blocks >> 32);
 }
 
-static inline void ext4fs_bg_free_inodes_dec(struct ext2_block_group *bg)
+static inline void ext4fs_bg_free_inodes_dec
+   (struct ext2_block_group *bg, const struct ext_filesystem *fs)
 {
-   bg->free_inodes = cpu_to_le16(le16_to_cpu(bg->free_inodes) - 1);
+   uint32_t free_inodes = le16_to_cpu(bg->free_inodes);
+   if (fs->gdsize == 64)
+   free_inodes += le16_to_cpu(bg->free_inodes_high) << 16;
+   free_inodes--;
+
+   bg->free_inodes = cpu_to_le16(free_inodes & 0x);
+   if (fs->gdsize == 64)
+   bg->free_inodes_high = cpu_to_le16(free_inodes >> 16);
 }
 
-static inline void ext4fs_bg_free_blocks_dec(struct ext2_block_group *bg)
+static inline void ext4fs_bg_free_blocks_dec
+   (struct ext2_block_group *bg, const struct ext_filesystem *fs)
 {
-   bg->free_blocks = cpu_to_le16(le16_to_cpu(bg->free_blocks) - 1);
+   uint32_t free_blocks = le16_to_cpu(bg->free_blocks);
+   if (fs->gdsize == 64)
+   free_blocks += le16_to_cpu(bg->free_blocks_high) << 16;
+   free_blocks--;
+
+   bg->free_blocks = cpu_to_le16(free_blocks & 0x);
+   if (fs->gdsize == 64)
+   bg->free_blocks_high = cpu_to_le16(free_blocks >> 16);
 }
 
-static inline void ext4fs_bg_itable_unused_dec(struct ext2_block_group *bg)
+static inline void ext4fs_bg_itable_unused_dec
+   (struct ext2_block_group *bg, const struct ext_filesystem *fs)
 {
-   bg->bg_itable_unused = cpu_to_le16(le16_to_cpu(bg->bg_itable_unused) - 
1);
+   uint32_t free_inodes = le16_to_cpu(bg->bg_itable_unused);
+   if (fs->gdsize == 64)
+   free_inodes += le16_to_cpu(bg->bg_itable_unused_high) << 16;
+   free_inodes--;
+
+   bg->bg_itable_unused = cpu_to_le16(free_inodes & 0x);
+   if (fs->gdsize == 64)
+   bg->bg_itable_unused_high = cpu_to_le16(free_inodes >> 16);
 }
 
 uint64_t ext4fs_sb_get_free_blocks(const struct ext2_sblock *sb)
@@ -958,7 +987,7 @@ uint32_t ext4fs_get_new_blk_no(void)
fs->curr_blkno = fs->curr_blkno +
(i * fs->blksz * 8);
fs->first_pass_bbmap++;
-   ext4fs_bg_free_blocks_dec(bgd);
+   ext4fs_bg_free_blocks_dec(bgd, fs);
ext4fs_sb_free_blocks_dec(fs->sb);
status = ext4fs_devread(b_bitmap_blk *
fs->sect_perblk,
@@ -1033,7 +1062,7 @@ restart:
 
prev_bg_bitmap_index = bg_idx;
}
-   ext4fs_bg_free_blocks_dec(bgd);
+   ext4fs_bg_free_blocks_dec(bgd, fs);
ext4fs_sb_free_blocks_dec(fs->sb);
goto success;
}
@@ -1092,9 +1121,9 @@ int ext4fs_get_new_inode_no(void)
fs->curr_inode_no = fs->curr_inode_no +
(i * inodes_per_grp);
fs->first_pass_ibmap++;
-   ext4fs_bg_free_inodes_dec(bgd);
+   ext4fs_bg_free_inodes_dec(bgd, fs);
if (has_gdt_chksum)
-   ext4fs_bg_itable_unused_dec(bgd);
+   ext4fs_bg_itable_unused_dec(bgd, fs);
ext4fs_sb_free_inodes_dec(fs->sb);
status = ext4fs_devread(i_bitmap_blk *
fs->sect_perblk,
@@ -1148,7 +1177,7 @@ restart:
   

[U-Boot] [PATCH v2 3/7] ext4: Add helper functions for block group descriptor field access

2016-09-19 Thread Stefan Brüns
The helper functions encapsulate access of the block group descriptors,
independent of group descriptor size. The helpers also deal with the
endianess of the fields, and with split fields like free_blocks/
free_blocks_high.

Signed-off-by: Stefan Brüns <stefan.bru...@rwth-aachen.de>
---
v2: include ext4fs_bg_get_inode_table_id(...) even if CONFIG_EXT4_WRITE
is not defined

 fs/ext4/ext4_common.c | 82 +++
 fs/ext4/ext4_common.h | 12 
 2 files changed, 94 insertions(+)

diff --git a/fs/ext4/ext4_common.c b/fs/ext4/ext4_common.c
index 2df4f8b..81740f8 100644
--- a/fs/ext4/ext4_common.c
+++ b/fs/ext4/ext4_common.c
@@ -47,6 +47,12 @@ struct ext2_inode *g_parent_inode;
 static int symlinknest;
 
 #if defined(CONFIG_EXT4_WRITE)
+struct ext2_block_group *ext4fs_get_group_descriptor
+   (const struct ext_filesystem *fs, uint32_t bg_idx)
+{
+   return (struct ext2_block_group *)(fs->gdtable + (bg_idx * fs->gdsize));
+}
+
 static inline void ext4fs_sb_free_inodes_dec(struct ext2_sblock *sb)
 {
sb->free_inodes = cpu_to_le32(le32_to_cpu(sb->free_inodes) - 1);
@@ -72,6 +78,82 @@ static inline void ext4fs_bg_itable_unused_dec(struct 
ext2_block_group *bg)
bg->bg_itable_unused = cpu_to_le16(le16_to_cpu(bg->bg_itable_unused) - 
1);
 }
 
+uint64_t ext4fs_sb_get_free_blocks(const struct ext2_sblock *sb)
+{
+   uint64_t free_blocks = le32_to_cpu(sb->free_blocks);
+   free_blocks += (uint64_t)le32_to_cpu(sb->free_blocks_high) << 32;
+   return free_blocks;
+}
+
+void ext4fs_sb_set_free_blocks(struct ext2_sblock *sb, uint64_t free_blocks)
+{
+   sb->free_blocks = cpu_to_le32(free_blocks & 0x);
+   sb->free_blocks_high = cpu_to_le16(free_blocks >> 32);
+}
+
+uint32_t ext4fs_bg_get_free_blocks(const struct ext2_block_group *bg,
+  const struct ext_filesystem *fs)
+{
+   uint32_t free_blocks = le16_to_cpu(bg->free_blocks);
+   if (fs->gdsize == 64)
+   free_blocks += le16_to_cpu(bg->free_blocks_high) << 16;
+   return free_blocks;
+}
+
+static inline
+uint32_t ext4fs_bg_get_free_inodes(const struct ext2_block_group *bg,
+  const struct ext_filesystem *fs)
+{
+   uint32_t free_inodes = le16_to_cpu(bg->free_inodes);
+   if (fs->gdsize == 64)
+   free_inodes += le16_to_cpu(bg->free_inodes_high) << 16;
+   return free_inodes;
+}
+
+static inline uint16_t ext4fs_bg_get_flags(const struct ext2_block_group *bg)
+{
+   return le16_to_cpu(bg->bg_flags);
+}
+
+static inline void ext4fs_bg_set_flags(struct ext2_block_group *bg,
+  uint16_t flags)
+{
+   bg->bg_flags = cpu_to_le16(flags);
+}
+
+/* Block number of the block bitmap */
+uint64_t ext4fs_bg_get_block_id(const struct ext2_block_group *bg,
+   const struct ext_filesystem *fs)
+{
+   uint64_t block_nr = le32_to_cpu(bg->block_id);
+   if (fs->gdsize == 64)
+   block_nr += (uint64_t)le32_to_cpu(bg->block_id_high) << 32;
+   return block_nr;
+}
+
+/* Block number of the inode bitmap */
+uint64_t ext4fs_bg_get_inode_id(const struct ext2_block_group *bg,
+   const struct ext_filesystem *fs)
+{
+   uint64_t block_nr = le32_to_cpu(bg->inode_id);
+   if (fs->gdsize == 64)
+   block_nr += (uint64_t)le32_to_cpu(bg->inode_id_high) << 32;
+   return block_nr;
+}
+#endif
+
+/* Block number of the inode table */
+uint64_t ext4fs_bg_get_inode_table_id(const struct ext2_block_group *bg,
+ const struct ext_filesystem *fs)
+{
+   uint64_t block_nr = le32_to_cpu(bg->inode_table_id);
+   if (fs->gdsize == 64)
+   block_nr +=
+   (uint64_t)le32_to_cpu(bg->inode_table_id_high) << 32;
+   return block_nr;
+}
+
+#if defined(CONFIG_EXT4_WRITE)
 uint32_t ext4fs_div_roundup(uint32_t size, uint32_t n)
 {
uint32_t res = size / n;
diff --git a/fs/ext4/ext4_common.h b/fs/ext4/ext4_common.h
index cc9d0c5..99d49e6 100644
--- a/fs/ext4/ext4_common.h
+++ b/fs/ext4/ext4_common.h
@@ -74,5 +74,17 @@ void ext4fs_allocate_blocks(struct ext2_inode *file_inode,
unsigned int total_remaining_blocks,
unsigned int *total_no_of_block);
 void put_ext4(uint64_t off, void *buf, uint32_t size);
+struct ext2_block_group *ext4fs_get_group_descriptor
+   (const struct ext_filesystem *fs, uint32_t bg_idx);
+uint64_t ext4fs_bg_get_block_id(const struct ext2_block_group *bg,
+   const struct ext_filesystem *fs);
+uint64_t ext4fs_bg_get_inode_id(const struct ext2_block_group *bg,
+   const struct ext_filesystem *fs);
+uint64_t ext4fs_bg_get_inode_table_id(const struct ext

[U-Boot] [PATCH 7/7] ext4: Revert rejection of 64bit enabled ext4 fs

2016-09-16 Thread Stefan Brüns
Enable mounting of ext4 fs with 64bit feature, as it is supported now.
These had been disabled in 6f94ab6656ceffb3f2a972c8de4c554502b6f2b7.

Signed-off-by: Stefan Brüns <stefan.bru...@rwth-aachen.de>
---
 fs/ext4/ext4_common.c | 9 -
 1 file changed, 9 deletions(-)

diff --git a/fs/ext4/ext4_common.c b/fs/ext4/ext4_common.c
index 61c4d19..bd81744 100644
--- a/fs/ext4/ext4_common.c
+++ b/fs/ext4/ext4_common.c
@@ -2337,15 +2337,6 @@ int ext4fs_mount(unsigned part_length)
if (le16_to_cpu(data->sblock.magic) != EXT2_MAGIC)
goto fail;
 
-   /*
-* The 64bit feature was enabled when metadata_csum was enabled
-* and we do not support metadata_csum (and cannot reliably find
-* files when it is set.  Refuse to mount.
-*/
-   if (le32_to_cpu(data->sblock.feature_incompat) & 
EXT4_FEATURE_INCOMPAT_64BIT) {
-   printf("Unsupported feature found (64bit, possibly 
metadata_csum), not mounting\n");
-   goto fail;
-   }
 
if (le32_to_cpu(data->sblock.revision_level) == 0) {
fs->inodesz = 128;
-- 
2.10.0

___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


[U-Boot] [PATCH 5/7] ext4: Use helper function to access group descriptor and its fields

2016-09-16 Thread Stefan Brüns
The descriptor size is variable, thus array indices are not generically
applicable. The larger group descriptors also contain e.g. high parts
of block numbers, which have to be read and written.

Signed-off-by: Stefan Brüns <stefan.bru...@rwth-aachen.de>
---
 fs/ext4/ext4_common.c | 125 --
 fs/ext4/ext4_write.c  | 165 +++---
 include/ext4fs.h  |   1 -
 3 files changed, 154 insertions(+), 137 deletions(-)

diff --git a/fs/ext4/ext4_common.c b/fs/ext4/ext4_common.c
index 24610ca..0c2ac47 100644
--- a/fs/ext4/ext4_common.c
+++ b/fs/ext4/ext4_common.c
@@ -391,7 +391,7 @@ uint16_t ext4fs_checksum_update(uint32_t i)
uint16_t crc = 0;
__le32 le32_i = cpu_to_le32(i);
 
-   desc = (struct ext2_block_group *)>bgd[i];
+   desc = ext4fs_get_group_descriptor(fs, i);
if (le32_to_cpu(fs->sb->feature_ro_compat) & 
EXT4_FEATURE_RO_COMPAT_GDT_CSUM) {
int offset = offsetof(struct ext2_block_group, bg_checksum);
 
@@ -931,39 +931,41 @@ uint32_t ext4fs_get_new_blk_no(void)
char *zero_buffer = zalloc(fs->blksz);
if (!journal_buffer || !zero_buffer)
goto fail;
-   struct ext2_block_group *bgd = (struct ext2_block_group *)fs->gdtable;
 
if (fs->first_pass_bbmap == 0) {
for (i = 0; i < fs->no_blkgrp; i++) {
-   if (le16_to_cpu(bgd[i].free_blocks)) {
-   if (le16_to_cpu(bgd[i].bg_flags) & 
EXT4_BG_BLOCK_UNINIT) {
-   uint16_t new_flags;
-   
put_ext4((uint64_t)le32_to_cpu(bgd[i].block_id) * fs->blksz,
-zero_buffer, fs->blksz);
-   new_flags = 
le16_to_cpu(bgd[i].bg_flags) & ~EXT4_BG_BLOCK_UNINIT;
-   bgd[i].bg_flags = 
cpu_to_le16(new_flags);
+   struct ext2_block_group *bgd = NULL;
+   bgd = ext4fs_get_group_descriptor(fs, i);
+   if (ext4fs_bg_get_free_blocks(bgd, fs)) {
+   uint16_t bg_flags = ext4fs_bg_get_flags(bgd);
+   uint64_t b_bitmap_blk =
+   ext4fs_bg_get_block_id(bgd, fs);
+   if (bg_flags & EXT4_BG_BLOCK_UNINIT) {
memcpy(fs->blk_bmaps[i], zero_buffer,
   fs->blksz);
+   put_ext4(b_bitmap_blk * fs->blksz,
+fs->blk_bmaps[i], fs->blksz);
+   bg_flags &= ~EXT4_BG_BLOCK_UNINIT;
+   ext4fs_bg_set_flags(bgd, bg_flags);
}
fs->curr_blkno =
_get_new_blk_no(fs->blk_bmaps[i]);
if (fs->curr_blkno == -1)
-   /* if block bitmap is completely fill */
+   /* block bitmap is completely filled */
continue;
fs->curr_blkno = fs->curr_blkno +
(i * fs->blksz * 8);
fs->first_pass_bbmap++;
-   ext4fs_bg_free_blocks_dec([i]);
+   ext4fs_bg_free_blocks_dec(bgd);
ext4fs_sb_free_blocks_dec(fs->sb);
-   status = ext4fs_devread(
-   
(lbaint_t)le32_to_cpu(bgd[i].block_id) *
-   fs->sect_perblk, 0,
-   fs->blksz,
+   status = ext4fs_devread(b_bitmap_blk *
+   fs->sect_perblk,
+   0, fs->blksz,
journal_buffer);
if (status == 0)
goto fail;
if (ext4fs_log_journal(journal_buffer,
-   
le32_to_cpu(bgd[i].block_id)))
+  b_bitmap_blk))
goto fail;
goto success;
} else {
@@ -990,7 +992,9 @@ restart:
if (bg_idx >= fs->no_blkgrp)
goto fail;
 
-  

[U-Boot] [PATCH 1/7] ext4: Update ext2/3/4 superblock, group descriptor and inode structures

2016-09-16 Thread Stefan Brüns
Most importantly, the superblock provides the used group descriptor size,
which is required for the EXT4_FEATURE_INCOMPAT_64BIT.

Signed-off-by: Stefan Brüns <stefan.bru...@rwth-aachen.de>
---
 include/ext_common.h | 50 ++
 1 file changed, 46 insertions(+), 4 deletions(-)

diff --git a/include/ext_common.h b/include/ext_common.h
index 25216ca..07b61fa 100644
--- a/include/ext_common.h
+++ b/include/ext_common.h
@@ -99,6 +99,33 @@ struct ext2_sblock {
char volume_name[16];
char last_mounted_on[64];
__le32 compression_info;
+   uint8_t prealloc_blocks;
+   uint8_t prealloc_dir_blocks;
+   __le16 reserved_gdt_blocks;
+   uint8_t journal_uuid[16];
+   __le32 journal_inode;
+   __le32 journal_dev;
+   __le32 last_orphan;
+   __le32 hash_seed[4];
+   uint8_t default_hash_version;
+   uint8_t journal_backup_type;
+   __le16 descriptor_size;
+   __le32 default_mount_options;
+   __le32 first_meta_block_group;
+   __le32 mkfs_time;
+   __le32 journal_blocks[17];
+   __le32 total_blocks_high;
+   __le32 reserved_blocks_high;
+   __le32 free_blocks_high;
+   __le16 min_extra_inode_size;
+   __le16 want_extra_inode_size;
+   __le32 flags;
+   __le16 raid_stride;
+   __le16 mmp_interval;
+   __le64 mmp_block;
+   __le32 raid_stripe_width;
+   uint8_t log2_groups_per_flex;
+   uint8_t checksum_type;
 };
 
 struct ext2_block_group {
@@ -109,9 +136,23 @@ struct ext2_block_group {
__le16 free_inodes; /* Free inodes count */
__le16 used_dir_cnt;/* Directories count */
__le16 bg_flags;
-   __le32 bg_reserved[2];
+   __le32 bg_exclude_bitmap;
+   __le16 bg_block_id_csum;
+   __le16 bg_inode_id_csum;
__le16 bg_itable_unused; /* Unused inodes count */
-   __le16 bg_checksum; /* crc16(s_uuid+grouo_num+group_desc)*/
+   __le16 bg_checksum; /* crc16(s_uuid+group_num+group_desc)*/
+   /* following fields only exist if descriptor size is 64 */
+   __le32 block_id_high;
+   __le32 inode_id_high;
+   __le32 inode_table_id_high;
+   __le16 free_blocks_high;
+   __le16 free_inodes_high;
+   __le16 used_dir_cnt_high;
+   __le16 bg_itable_unused_high;
+   __le32 bg_exclude_bitmap_high;
+   __le16 bg_block_id_csum_high;
+   __le16 bg_inode_id_csum_high;
+   __le32 bg_reserved;
 };
 
 /* The ext2 inode. */
@@ -125,7 +166,7 @@ struct ext2_inode {
__le32 dtime;
__le16 gid;
__le16 nlinks;
-   __le32 blockcnt;/* Blocks of 512 bytes!! */
+   __le32 blockcnt;/* Blocks of either 512 or block_size bytes */
__le32 flags;
__le32 osd1;
union {
@@ -136,10 +177,11 @@ struct ext2_inode {
__le32 triple_indir_block;
} blocks;
char symlink[60];
+   char inline_data[60];
} b;
__le32 version;
__le32 acl;
-   __le32 dir_acl;
+   __le32 size_high;   /* previously dir_acl, but never used */
__le32 fragment_addr;
__le32 osd2[3];
 };
-- 
2.10.0

___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


[U-Boot] [PATCH 6/7] ext4: Respect group descriptor size when adjusting free counts

2016-09-16 Thread Stefan Brüns
Also adjust high 16/32 bits when free inode/block counts are modified.

Signed-off-by: Stefan Brüns <stefan.bru...@rwth-aachen.de>
---
 fs/ext4/ext4_common.c | 53 +++
 fs/ext4/ext4_write.c  | 40 ++
 2 files changed, 69 insertions(+), 24 deletions(-)

diff --git a/fs/ext4/ext4_common.c b/fs/ext4/ext4_common.c
index 0c2ac47..61c4d19 100644
--- a/fs/ext4/ext4_common.c
+++ b/fs/ext4/ext4_common.c
@@ -58,24 +58,53 @@ static inline void ext4fs_sb_free_inodes_dec(struct 
ext2_sblock *sb)
sb->free_inodes = cpu_to_le32(le32_to_cpu(sb->free_inodes) - 1);
 }
 
-static inline void ext4fs_bg_free_inodes_dec(struct ext2_block_group *bg)
+static inline void ext4fs_bg_free_inodes_dec
+   (struct ext2_block_group *bg, const struct ext_filesystem *fs)
 {
-   bg->free_inodes = cpu_to_le16(le16_to_cpu(bg->free_inodes) - 1);
+   uint32_t free_inodes = le16_to_cpu(bg->free_inodes);
+   if (fs->gdsize == 64)
+   free_inodes += le16_to_cpu(bg->free_inodes_high) << 16;
+   free_inodes--;
+
+   bg->free_inodes = cpu_to_le16(free_inodes & 0x);
+   if (fs->gdsize == 64)
+   bg->free_inodes_high = cpu_to_le16(free_inodes >> 16);
 }
 
-static inline void ext4fs_bg_free_blocks_dec(struct ext2_block_group *bg)
+static inline void ext4fs_bg_free_blocks_dec
+   (struct ext2_block_group *bg, const struct ext_filesystem *fs)
 {
-   bg->free_blocks = cpu_to_le16(le16_to_cpu(bg->free_blocks) - 1);
+   uint32_t free_blocks = le16_to_cpu(bg->free_blocks);
+   if (fs->gdsize == 64)
+   free_blocks += le16_to_cpu(bg->free_blocks_high) << 16;
+   free_blocks--;
+
+   bg->free_blocks = cpu_to_le16(free_blocks & 0x);
+   if (fs->gdsize == 64)
+   bg->free_blocks_high = cpu_to_le16(free_blocks >> 16);
 }
 
 static inline void ext4fs_sb_free_blocks_dec(struct ext2_sblock *sb)
 {
-   sb->free_blocks = cpu_to_le32(le32_to_cpu(sb->free_blocks) - 1);
+   uint64_t free_blocks = le32_to_cpu(sb->free_blocks);
+   free_blocks += (uint64_t)le32_to_cpu(sb->free_blocks_high) << 32;
+   free_blocks--;
+
+   sb->free_blocks = cpu_to_le32(free_blocks & 0x);
+   sb->free_blocks_high = cpu_to_le16(free_blocks >> 32);
 }
 
-static inline void ext4fs_bg_itable_unused_dec(struct ext2_block_group *bg)
+static inline void ext4fs_bg_itable_unused_dec
+   (struct ext2_block_group *bg, const struct ext_filesystem *fs)
 {
-   bg->bg_itable_unused = cpu_to_le16(le16_to_cpu(bg->bg_itable_unused) - 
1);
+   uint32_t free_inodes = le16_to_cpu(bg->bg_itable_unused);
+   if (fs->gdsize == 64)
+   free_inodes += le16_to_cpu(bg->bg_itable_unused_high) << 16;
+   free_inodes--;
+
+   bg->bg_itable_unused = cpu_to_le16(free_inodes & 0x);
+   if (fs->gdsize == 64)
+   bg->bg_itable_unused_high = cpu_to_le16(free_inodes >> 16);
 }
 
 uint64_t ext4fs_sb_get_free_blocks(const struct ext2_sblock *sb)
@@ -956,7 +985,7 @@ uint32_t ext4fs_get_new_blk_no(void)
fs->curr_blkno = fs->curr_blkno +
(i * fs->blksz * 8);
fs->first_pass_bbmap++;
-   ext4fs_bg_free_blocks_dec(bgd);
+   ext4fs_bg_free_blocks_dec(bgd, fs);
ext4fs_sb_free_blocks_dec(fs->sb);
status = ext4fs_devread(b_bitmap_blk *
fs->sect_perblk,
@@ -1031,7 +1060,7 @@ restart:
 
prev_bg_bitmap_index = bg_idx;
}
-   ext4fs_bg_free_blocks_dec(bgd);
+   ext4fs_bg_free_blocks_dec(bgd, fs);
ext4fs_sb_free_blocks_dec(fs->sb);
goto success;
}
@@ -1090,9 +1119,9 @@ int ext4fs_get_new_inode_no(void)
fs->curr_inode_no = fs->curr_inode_no +
(i * inodes_per_grp);
fs->first_pass_ibmap++;
-   ext4fs_bg_free_inodes_dec(bgd);
+   ext4fs_bg_free_inodes_dec(bgd, fs);
if (has_gdt_chksum)
-   ext4fs_bg_itable_unused_dec(bgd);
+   ext4fs_bg_itable_unused_dec(bgd, fs);
ext4fs_sb_free_inodes_dec(fs->sb);
status = ext4fs_devread(i_bitmap_blk *
fs->sect_perblk,
@@ -1146,7 +1175,7 @@ restart:
 

[U-Boot] [PATCH 3/7] ext4: Add helper functions for block group descriptor field access

2016-09-16 Thread Stefan Brüns
The helper functions encapsulate access of the block group descriptors,
independent of group descriptor size. The helpers also deal with the
endianess of the fields, and with split fields like free_blocks/
free_blocks_high.

Signed-off-by: Stefan Brüns <stefan.bru...@rwth-aachen.de>
---
 fs/ext4/ext4_common.c | 80 +++
 fs/ext4/ext4_common.h | 12 
 2 files changed, 92 insertions(+)

diff --git a/fs/ext4/ext4_common.c b/fs/ext4/ext4_common.c
index 416a9db..9e5bca0 100644
--- a/fs/ext4/ext4_common.c
+++ b/fs/ext4/ext4_common.c
@@ -47,6 +47,12 @@ struct ext2_inode *g_parent_inode;
 static int symlinknest;
 
 #if defined(CONFIG_EXT4_WRITE)
+struct ext2_block_group *ext4fs_get_group_descriptor
+   (const struct ext_filesystem *fs, uint32_t bg_idx)
+{
+   return (struct ext2_block_group *)(fs->gdtable + (bg_idx * fs->gdsize));
+}
+
 static inline void ext4fs_sb_free_inodes_dec(struct ext2_sblock *sb)
 {
sb->free_inodes = cpu_to_le32(le32_to_cpu(sb->free_inodes) - 1);
@@ -72,6 +78,80 @@ static inline void ext4fs_bg_itable_unused_dec(struct 
ext2_block_group *bg)
bg->bg_itable_unused = cpu_to_le16(le16_to_cpu(bg->bg_itable_unused) - 
1);
 }
 
+uint64_t ext4fs_sb_get_free_blocks(const struct ext2_sblock *sb)
+{
+   uint64_t free_blocks = le32_to_cpu(sb->free_blocks);
+   free_blocks += (uint64_t)le32_to_cpu(sb->free_blocks_high) << 32;
+   return free_blocks;
+}
+
+void ext4fs_sb_set_free_blocks(struct ext2_sblock *sb, uint64_t free_blocks)
+{
+   sb->free_blocks = cpu_to_le32(free_blocks & 0x);
+   sb->free_blocks_high = cpu_to_le16(free_blocks >> 32);
+}
+
+uint32_t ext4fs_bg_get_free_blocks(const struct ext2_block_group *bg,
+  const struct ext_filesystem *fs)
+{
+   uint32_t free_blocks = le16_to_cpu(bg->free_blocks);
+   if (fs->gdsize == 64)
+   free_blocks += le16_to_cpu(bg->free_blocks_high) << 16;
+   return free_blocks;
+}
+
+static inline
+uint32_t ext4fs_bg_get_free_inodes(const struct ext2_block_group *bg,
+  const struct ext_filesystem *fs)
+{
+   uint32_t free_inodes = le16_to_cpu(bg->free_inodes);
+   if (fs->gdsize == 64)
+   free_inodes += le16_to_cpu(bg->free_inodes_high) << 16;
+   return free_inodes;
+}
+
+static inline uint16_t ext4fs_bg_get_flags(const struct ext2_block_group *bg)
+{
+   return le16_to_cpu(bg->bg_flags);
+}
+
+static inline void ext4fs_bg_set_flags(struct ext2_block_group *bg,
+  uint16_t flags)
+{
+   bg->bg_flags = cpu_to_le16(flags);
+}
+
+/* Block number of the block bitmap */
+uint64_t ext4fs_bg_get_block_id(const struct ext2_block_group *bg,
+   const struct ext_filesystem *fs)
+{
+   uint64_t block_nr = le32_to_cpu(bg->block_id);
+   if (fs->gdsize == 64)
+   block_nr += (uint64_t)le32_to_cpu(bg->block_id_high) << 32;
+   return block_nr;
+}
+
+/* Block number of the inode bitmap */
+uint64_t ext4fs_bg_get_inode_id(const struct ext2_block_group *bg,
+   const struct ext_filesystem *fs)
+{
+   uint64_t block_nr = le32_to_cpu(bg->inode_id);
+   if (fs->gdsize == 64)
+   block_nr += (uint64_t)le32_to_cpu(bg->inode_id_high) << 32;
+   return block_nr;
+}
+
+/* Block number of the inode table */
+uint64_t ext4fs_bg_get_inode_table_id(const struct ext2_block_group *bg,
+ const struct ext_filesystem *fs)
+{
+   uint64_t block_nr = le32_to_cpu(bg->inode_table_id);
+   if (fs->gdsize == 64)
+   block_nr +=
+   (uint64_t)le32_to_cpu(bg->inode_table_id_high) << 32;
+   return block_nr;
+}
+
 uint32_t ext4fs_div_roundup(uint32_t size, uint32_t n)
 {
uint32_t res = size / n;
diff --git a/fs/ext4/ext4_common.h b/fs/ext4/ext4_common.h
index cc9d0c5..99d49e6 100644
--- a/fs/ext4/ext4_common.h
+++ b/fs/ext4/ext4_common.h
@@ -74,5 +74,17 @@ void ext4fs_allocate_blocks(struct ext2_inode *file_inode,
unsigned int total_remaining_blocks,
unsigned int *total_no_of_block);
 void put_ext4(uint64_t off, void *buf, uint32_t size);
+struct ext2_block_group *ext4fs_get_group_descriptor
+   (const struct ext_filesystem *fs, uint32_t bg_idx);
+uint64_t ext4fs_bg_get_block_id(const struct ext2_block_group *bg,
+   const struct ext_filesystem *fs);
+uint64_t ext4fs_bg_get_inode_id(const struct ext2_block_group *bg,
+   const struct ext_filesystem *fs);
+uint64_t ext4fs_bg_get_inode_table_id(const struct ext2_block_group *bg,
+   const struct ext_filesystem *fs);
+uint64_t ext4fs_sb_get_free_blocks(const struct ext2_sblock *sb);
+void ext4fs_sb

[U-Boot] [PATCH 0/7] Add support for ext4 with enabled 64bit feature

2016-09-16 Thread Stefan Brüns
The EXT4_FEATURE_INCOMPAT_64BIT changes the on disk layout. Use the
correct structure sizes/offsets and respect split high/low free
inode/block counts.

Stefan Brüns (7):
  ext4: Update ext2/3/4 superblock, group descriptor and inode
structures
  ext4: determine group descriptor size for 64bit feature
  ext4: Add helper functions for block group descriptor field access
  ext4: Use correct descriptor size when reading the block group
descriptor
  ext4: Use helper function to access group descriptor and its fields
  ext4: Respect group descriptor size when adjusting free counts
  ext4: Revert rejection of 64bit enabled ext4 fs

 fs/ext4/ext4_common.c | 283 +++---
 fs/ext4/ext4_common.h |  12 +++
 fs/ext4/ext4_write.c  | 189 +++--
 include/ext4fs.h  |   3 +-
 include/ext_common.h  |  50 -
 5 files changed, 368 insertions(+), 169 deletions(-)

-- 
2.10.0

___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


[U-Boot] [PATCH 2/7] ext4: determine group descriptor size for 64bit feature

2016-09-16 Thread Stefan Brüns
If EXT4_FEATURE_INCOMPAT_64BIT is set, the descriptor can be read from
the superblocks, otherwise it defaults to 32.

Signed-off-by: Stefan Brüns <stefan.bru...@rwth-aachen.de>
---
 fs/ext4/ext4_common.c | 18 ++
 include/ext4fs.h  |  2 ++
 2 files changed, 16 insertions(+), 4 deletions(-)

diff --git a/fs/ext4/ext4_common.c b/fs/ext4/ext4_common.c
index a78b0b8..416a9db 100644
--- a/fs/ext4/ext4_common.c
+++ b/fs/ext4/ext4_common.c
@@ -2233,13 +2233,23 @@ int ext4fs_mount(unsigned part_length)
goto fail;
}
 
-   if (le32_to_cpu(data->sblock.revision_level) == 0)
+   if (le32_to_cpu(data->sblock.revision_level) == 0) {
fs->inodesz = 128;
-   else
+   } else {
+   debug("EXT4 features COMPAT: %08x INCOMPAT: %08x RO_COMPAT: 
%08x\n",
+ __le32_to_cpu(data->sblock.feature_compatibility),
+ __le32_to_cpu(data->sblock.feature_incompat),
+ __le32_to_cpu(data->sblock.feature_ro_compat));
+
fs->inodesz = le16_to_cpu(data->sblock.inode_size);
+   fs->gdsize = le32_to_cpu(data->sblock.feature_incompat) &
+   EXT4_FEATURE_INCOMPAT_64BIT ?
+   le16_to_cpu(data->sblock.descriptor_size) : 32;
+   }
 
-   debug("EXT2 rev %d, inode_size %d\n",
-  le32_to_cpu(data->sblock.revision_level), fs->inodesz);
+   debug("EXT2 rev %d, inode_size %d, descriptor size %d\n",
+ le32_to_cpu(data->sblock.revision_level),
+ fs->inodesz, fs->gdsize);
 
data->diropen.data = data;
data->diropen.ino = 2;
diff --git a/include/ext4fs.h b/include/ext4fs.h
index 6e31c73..7e1ee6c 100644
--- a/include/ext4fs.h
+++ b/include/ext4fs.h
@@ -87,6 +87,8 @@ struct ext_filesystem {
uint32_t inodesz;
/* Sectors per Block */
uint32_t sect_perblk;
+   /* Group Descriptor size */
+   uint16_t gdsize;
/* Group Descriptor Block Number */
uint32_t gdtable_blkno;
/* Total block groups of partition */
-- 
2.10.0

___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


[U-Boot] [PATCH 4/7] ext4: Use correct descriptor size when reading the block group descriptor

2016-09-16 Thread Stefan Brüns
The correct descriptor size must be used when calculating offsets, and
also to read the correct amount of data.

Signed-off-by: Stefan Brüns <stefan.bru...@rwth-aachen.de>
---
 fs/ext4/ext4_common.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/fs/ext4/ext4_common.c b/fs/ext4/ext4_common.c
index 9e5bca0..24610ca 100644
--- a/fs/ext4/ext4_common.c
+++ b/fs/ext4/ext4_common.c
@@ -1525,20 +1525,20 @@ static int ext4fs_blockgroup
long int blkno;
unsigned int blkoff, desc_per_blk;
int log2blksz = get_fs()->dev_desc->log2blksz;
+   int desc_size = get_fs()->gdsize;
 
-   desc_per_blk = EXT2_BLOCK_SIZE(data) / sizeof(struct ext2_block_group);
+   desc_per_blk = EXT2_BLOCK_SIZE(data) / desc_size;
 
blkno = le32_to_cpu(data->sblock.first_data_block) + 1 +
group / desc_per_blk;
-   blkoff = (group % desc_per_blk) * sizeof(struct ext2_block_group);
+   blkoff = (group % desc_per_blk) * desc_size;
 
debug("ext4fs read %d group descriptor (blkno %ld blkoff %u)\n",
  group, blkno, blkoff);
 
return ext4fs_devread((lbaint_t)blkno <<
  (LOG2_BLOCK_SIZE(data) - log2blksz),
- blkoff, sizeof(struct ext2_block_group),
- (char *)blkgrp);
+ blkoff, desc_size, (char *)blkgrp);
 }
 
 int ext4fs_read_inode(struct ext2_data *data, int ino, struct ext2_inode 
*inode)
-- 
2.10.0

___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


[U-Boot] [PATCH v2 1/5] test/fs: Restructure file path specification to allow some flexibility

2016-09-13 Thread Stefan Brüns
Instead of providing the full path, specify directory and filename
separately. This allows to specify intermediate directories, required
for some additional tests.

Signed-off-by: Stefan Brüns <stefan.bru...@rwth-aachen.de>
---
 test/fs/fs-test.sh | 58 +-
 1 file changed, 22 insertions(+), 36 deletions(-)

diff --git a/test/fs/fs-test.sh b/test/fs/fs-test.sh
index 93679cb..f95350b 100755
--- a/test/fs/fs-test.sh
+++ b/test/fs/fs-test.sh
@@ -135,22 +135,6 @@ function create_image() {
fi
 }
 
-# 1st parameter is the FS type: fat/ext4
-# 2nd parameter is the name of small file
-# Returns filename which can be used for fat or ext4 for writing
-function fname_for_write() {
-   case $1 in
-   ext4)
-   # ext4 needs absolute path name of file
-   echo /${2}.w
-   ;;
-
-   *)
-   echo ${2}.w
-   ;;
-   esac
-}
-
 # 1st parameter is image file
 # 2nd parameter is file system type - fat/ext4
 # 3rd parameter is name of small file
@@ -166,11 +150,14 @@ function test_image() {
 
case "$2" in
fat)
+   FPATH=""
PREFIX="fat"
WRITE="write"
;;
 
ext4)
+   # ext4 needs absolute path
+   FPATH="/"
PREFIX="ext4"
WRITE="write"
;;
@@ -205,16 +192,15 @@ function test_image() {
 
esac
 
-   if [ -z "$6" ]; then
-   FILE_WRITE=`fname_for_write $2 $3`
-   FILE_SMALL=$3
-   FILE_BIG=$4
-   else
-   FILE_WRITE=$6/`fname_for_write $2 $3`
-   FILE_SMALL=$6/$3
-   FILE_BIG=$6/$4
+   # sb always uses full path to mointpoint, irrespective of filesystem
+   if [ "$5" = "sb" ]; then
+   FPATH=${6}/
fi
 
+   FILE_WRITE=${3}.w
+   FILE_SMALL=$3
+   FILE_BIG=$4
+
# In u-boot commands,  stands for host or hostfs
# hostfs maps to the host fs.
# host maps to the "sb bind" that we do
@@ -230,13 +216,13 @@ ${PREFIX}ls host${SUFFIX} $6
 # sb size hostfs - $3 for hostfs commands.
 # 1MB is 0x0010 
 # Test Case 2 - size of small file
-${PREFIX}size host${SUFFIX} $FILE_SMALL
+${PREFIX}size host${SUFFIX} ${FPATH}$FILE_SMALL
 printenv filesize
 setenv filesize
 
 # 2.5GB (1024*1024*2500) is 0x9C40 
 # Test Case 3 - size of big file
-${PREFIX}size host${SUFFIX} $FILE_BIG
+${PREFIX}size host${SUFFIX} ${FPATH}$FILE_BIG
 printenv filesize
 setenv filesize
 
@@ -245,14 +231,14 @@ setenv filesize
 # Last two parameters are size and offset.
 
 # Test Case 4a - Read full 1MB of small file
-${PREFIX}load host${SUFFIX} $addr $FILE_SMALL
+${PREFIX}load host${SUFFIX} $addr ${FPATH}$FILE_SMALL
 printenv filesize
 # Test Case 4b - Read full 1MB of small file
 md5sum $addr \$filesize
 setenv filesize
 
 # Test Case 5a - First 1MB of big file
-${PREFIX}load host${SUFFIX} $addr $FILE_BIG $length 0x0
+${PREFIX}load host${SUFFIX} $addr ${FPATH}$FILE_BIG $length 0x0
 printenv filesize
 # Test Case 5b - First 1MB of big file
 md5sum $addr \$filesize
@@ -260,7 +246,7 @@ setenv filesize
 
 # fails for ext as no offset support
 # Test Case 6a - Last 1MB of big file
-${PREFIX}load host${SUFFIX} $addr $FILE_BIG $length 0x9C30
+${PREFIX}load host${SUFFIX} $addr ${FPATH}$FILE_BIG $length 0x9C30
 printenv filesize
 # Test Case 6b - Last 1MB of big file
 md5sum $addr \$filesize
@@ -268,7 +254,7 @@ setenv filesize
 
 # fails for ext as no offset support
 # Test Case 7a - One from the last 1MB chunk of 2GB
-${PREFIX}load host${SUFFIX} $addr $FILE_BIG $length 0x7FF0
+${PREFIX}load host${SUFFIX} $addr ${FPATH}$FILE_BIG $length 0x7FF0
 printenv filesize
 # Test Case 7b - One from the last 1MB chunk of 2GB
 md5sum $addr \$filesize
@@ -276,7 +262,7 @@ setenv filesize
 
 # fails for ext as no offset support
 # Test Case 8a - One from the start 1MB chunk from 2GB
-${PREFIX}load host${SUFFIX} $addr $FILE_BIG $length 0x8000
+${PREFIX}load host${SUFFIX} $addr ${FPATH}$FILE_BIG $length 0x8000
 printenv filesize
 # Test Case 8b - One from the start 1MB chunk from 2GB
 md5sum $addr \$filesize
@@ -284,7 +270,7 @@ setenv filesize
 
 # fails for ext as no offset support
 # Test Case 9a - One 1MB chunk crossing the 2GB boundary
-${PREFIX}load host${SUFFIX} $addr $FILE_BIG $length 0x7FF8
+${PREFIX}load host${SUFFIX} $addr ${FPATH}$FILE_BIG $length 0x7FF8
 printenv filesize
 # Test Case 9b - One 1MB chunk crossing the 2GB boundary
 md5sum $addr \$filesize
@@ -292,17 +278,17 @@ setenv filesize
 
 # Generic failure case
 # Test Case 10 - 2MB chunk from the last 1MB of big file
-${PREFIX}load host${SUFFIX} $addr $FILE_BIG 0x0020 0x9C30

[U-Boot] [PATCH v2 3/5] test/fs: strip noise from filesystem code prior to checking results

2016-09-13 Thread Stefan Brüns
ext4 and fat code emit some diagnostic messages during command execution.
These additional lines force a match window size which strictly is not
necessary.

Signed-off-by: Stefan Brüns <stefan.bru...@rwth-aachen.de>
---
 test/fs/fs-test.sh | 26 +++---
 1 file changed, 15 insertions(+), 11 deletions(-)

diff --git a/test/fs/fs-test.sh b/test/fs/fs-test.sh
index 9615898..b9c2306 100755
--- a/test/fs/fs-test.sh
+++ b/test/fs/fs-test.sh
@@ -386,7 +386,7 @@ check_md5() {
# md5sum in u-boot has output of form:
# md5 for 0108 ... 0117 ==> 
# the 7th field is the actual md5
-   md5_src=`grep -A3 "$1" "$2" | grep "md5 for" | tr -d '\r'`
+   md5_src=`grep -A2 "$1" "$2" | grep "md5 for" | tr -d '\r'`
md5_src=($md5_src)
md5_src=${md5_src[6]}
 
@@ -431,45 +431,44 @@ function check_results() {
pass_fail "TC3: size of $4"
 
# Check read full mb of 1MB.file
-   grep -A6 "Test Case 4a " "$1" | grep -q "filesize=10"
+   grep -A4 "Test Case 4a " "$1" | grep -q "filesize=10"
pass_fail "TC4: load of $3 size"
check_md5 "Test Case 4b " "$1" "$2" 1 "TC4: load from $3"
 
# Check first mb of 2.5GB.file
-   grep -A6 "Test Case 5a " "$1" | grep -q "filesize=10"
+   grep -A4 "Test Case 5a " "$1" | grep -q "filesize=10"
pass_fail "TC5: load of 1st MB from $4 size"
check_md5 "Test Case 5b " "$1" "$2" 2 "TC5: load of 1st MB from $4"
 
# Check last mb of 2.5GB.file
-   grep -A6 "Test Case 6a " "$1" | grep -q "filesize=10"
+   grep -A4 "Test Case 6a " "$1" | grep -q "filesize=10"
pass_fail "TC6: load of last MB from $4 size"
check_md5 "Test Case 6b " "$1" "$2" 3 "TC6: load of last MB from $4"
 
# Check last 1mb chunk of 2gb from 2.5GB file
-   grep -A6 "Test Case 7a " "$1" | grep -q "filesize=10"
+   grep -A4 "Test Case 7a " "$1" | grep -q "filesize=10"
pass_fail "TC7: load of last 1mb chunk of 2GB from $4 size"
check_md5 "Test Case 7b " "$1" "$2" 4 \
"TC7: load of last 1mb chunk of 2GB from $4"
 
# Check first 1mb chunk after 2gb from 2.5GB file
-   grep -A6 "Test Case 8a " "$1" | grep -q "filesize=10"
+   grep -A4 "Test Case 8a " "$1" | grep -q "filesize=10"
pass_fail "TC8: load 1st MB chunk after 2GB from $4 size"
check_md5 "Test Case 8b " "$1" "$2" 5 \
"TC8: load 1st MB chunk after 2GB from $4"
 
# Check 1mb chunk crossing the 2gb boundary from 2.5GB file
-   grep -A6 "Test Case 9a " "$1" | grep -q "filesize=10"
+   grep -A4 "Test Case 9a " "$1" | grep -q "filesize=10"
pass_fail "TC9: load 1MB chunk crossing 2GB boundary from $4 size"
check_md5 "Test Case 9b " "$1" "$2" 6 \
"TC9: load 1MB chunk crossing 2GB boundary from $4"
 
# Check 2mb chunk from the last 1MB of 2.5GB file loads 1MB
-   grep -A6 "Test Case 10 " "$1" | grep -q "filesize=10"
+   grep -A5 "Test Case 10 " "$1" | grep -q "filesize=10"
pass_fail "TC10: load 2MB from the last 1MB of $4 loads 1MB"
 
# Check 1mb chunk write
-   grep -A3 "Test Case 11a " "$1" | \
-   egrep -q '1048576 bytes written|update journal'
+   grep -A2 "Test Case 11a " "$1" | grep -q '1048576 bytes written'
pass_fail "TC11: 1MB write to $3.w - write succeeded"
check_md5 "Test Case 11b " "$1" "$2" 1 \
"TC11: 1MB write to $3.w - content verified"
@@ -486,7 +485,12 @@ function test_fs_nonfs() {
OUT_FILE="${OUT}.$1.${fs}.out"
test_image $IMAGE $fs $SMALL_FILE $BIG_FILE $1 "" \
> ${OUT_FILE} 2>&1
-   check_results $OUT_FILE $MD5_FILE_FS $SMALL_FILE $BIG_FILE
+   # strip out noise from fs code
+   grep -v -e "File System is consistent\|update journal finished" \
+   -e "reading .*\.file\|writing .*\.file.w" \
+   < ${OUT_FILE} > ${OUT_FILE}_clean
+   check_results ${OUT_FILE}_clean $MD5_FILE_FS $SMALL_FILE \
+   $BIG_FILE
TOTAL_FAIL=$((TOTAL_FAIL + FAIL))
TOTAL_PASS=$((TOTAL_PASS + PASS))
echo "Summary: PASS: $PASS FAIL: $FAIL"
-- 
2.10.0

___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


[U-Boot] [PATCH v2 5/5] test/fs: Check writes using "." (same dir) relative path

2016-09-13 Thread Stefan Brüns
/ and /./ should reference the same file.

Signed-off-by: Stefan Brüns <stefan.bru...@rwth-aachen.de>
---
 test/fs/fs-test.sh | 29 -
 1 file changed, 28 insertions(+), 1 deletion(-)

diff --git a/test/fs/fs-test.sh b/test/fs/fs-test.sh
index 69abdab..520344b 100755
--- a/test/fs/fs-test.sh
+++ b/test/fs/fs-test.sh
@@ -299,6 +299,23 @@ setenv filesize
 # The write should fail, but the lookup should work
 # Test Case 12 - Check directory traversal
 ${PREFIX}${WRITE} host${SUFFIX} $addr ${FPATH}. 0x10
+
+# Read 1MB from small file
+${PREFIX}load host${SUFFIX} $addr ${FPATH}$FILE_SMALL
+# Write it via "same directory", i.e. "." dirent
+# Test Case 13a - Check directory traversal
+${PREFIX}${WRITE} host${SUFFIX} $addr ${FPATH}./${FILE_WRITE}2 \$filesize
+mw.b $addr 00 100
+${PREFIX}load host${SUFFIX} $addr ${FPATH}./${FILE_WRITE}2
+# Test Case 13b - Check md5 of written to is same as the one read from
+md5sum $addr \$filesize
+setenv filesize
+mw.b $addr 00 100
+${PREFIX}load host${SUFFIX} $addr ${FPATH}${FILE_WRITE}2
+# Test Case 13c - Check md5 of written to is same as the one read from
+md5sum $addr \$filesize
+setenv filesize
+#
 reset
 
 EOF
@@ -335,9 +352,10 @@ function create_files() {
&> /dev/null
fi
 
-   # Delete the small file which possibly is written as part of a
+   # Delete the small file copies which possibly are written as part of a
# previous test.
sudo rm -f "${MB1}.w"
+   sudo rm -f "${MB1}.w2"
 
# Generate the md5sums of reads that we will test against small file
dd if="${MB1}" bs=1M skip=0 count=1 2> /dev/null | md5sum > "$2"
@@ -482,6 +500,15 @@ function check_results() {
# Check lookup of 'dot' directory
grep -A4 "Test Case 12 " "$1" | grep -q 'Unable to write file'
pass_fail "TC12: 1MB write to . - write denied"
+
+   # Check directory traversal
+   grep -A2 "Test Case 13a " "$1" | grep -q '1048576 bytes written'
+   pass_fail "TC13: 1MB write to ./$3.w2 - write succeeded"
+   check_md5 "Test Case 13b " "$1" "$2" 1 \
+   "TC13: 1MB read from ./$3.w2 - content verified"
+   check_md5 "Test Case 13c " "$1" "$2" 1 \
+   "TC13: 1MB read from $3.w2 - content verified"
+
echo "** End $1"
 }
 
-- 
2.10.0

___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


[U-Boot] [PATCH v2 4/5] test/fs: Check ext4 behaviour if dirent is first entry in directory block

2016-09-13 Thread Stefan Brüns
This is a regression test for a crash happening if the first dirent
in the block matches. Code tried to access a predecessor entry which
does not exist.
The crash happened for any block, but "." is always the first entry in
the first directory block and thus easy to check for.

Signed-off-by: Stefan Brüns <stefan.bru...@rwth-aachen.de>
---
 test/fs/fs-test.sh | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/test/fs/fs-test.sh b/test/fs/fs-test.sh
index b9c2306..69abdab 100755
--- a/test/fs/fs-test.sh
+++ b/test/fs/fs-test.sh
@@ -293,6 +293,12 @@ ${PREFIX}load host${SUFFIX} $addr ${FPATH}$FILE_WRITE
 md5sum $addr \$filesize
 setenv filesize
 #
+
+# Next test case checks writing a file whose dirent
+# is the first in the block, which is always true for "."
+# The write should fail, but the lookup should work
+# Test Case 12 - Check directory traversal
+${PREFIX}${WRITE} host${SUFFIX} $addr ${FPATH}. 0x10
 reset
 
 EOF
@@ -472,6 +478,10 @@ function check_results() {
pass_fail "TC11: 1MB write to $3.w - write succeeded"
check_md5 "Test Case 11b " "$1" "$2" 1 \
"TC11: 1MB write to $3.w - content verified"
+
+   # Check lookup of 'dot' directory
+   grep -A4 "Test Case 12 " "$1" | grep -q 'Unable to write file'
+   pass_fail "TC12: 1MB write to . - write denied"
echo "** End $1"
 }
 
-- 
2.10.0

___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


[U-Boot] [PATCH v2 0/5] Enhance fs tests

2016-09-13 Thread Stefan Brüns
The first 3 patches do some cleanups for the current test, especially TC11
had some issues (strange match for expected output, use of unitialized
variable).

The last two patches add test cases for handling ".". Ext4 used to crash,
as a match on the first entry of a directory block was not handled
correctly.

v2:
  Updated:
test/fs: Restructure file path specification to allow some flexibility
  * avoid creation of paths with double slashes
test/fs: Check writes using "." (same dir) relative path
  * fix issues copied from TC11
  * delete written file in cleanup
  Added:
test/fs: remove use of undefined WRITE_FILE variable
test/fs: strip noise from filesystem code prior to checking results

Stefan Brüns (5):
  test/fs: Restructure file path specification to allow some flexibility
  test/fs: remove use of undefined WRITE_FILE variable
  test/fs: strip noise from filesystem code prior to checking results
  test/fs: Check ext4 behaviour if dirent is first entry in directory
block
  test/fs: Check writes using "." (same dir) relative path

 test/fs/fs-test.sh | 131 +++--
 1 file changed, 78 insertions(+), 53 deletions(-)

-- 
2.10.0

___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


[U-Boot] [PATCH v2 2/5] test/fs: remove use of undefined WRITE_FILE variable

2016-09-13 Thread Stefan Brüns
The write file is created from $SMALL_FILE by appending ".w" on all
other occurences in the code.

Signed-off-by: Stefan Brüns <stefan.bru...@rwth-aachen.de>
---
 test/fs/fs-test.sh | 10 --
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/test/fs/fs-test.sh b/test/fs/fs-test.sh
index f95350b..9615898 100755
--- a/test/fs/fs-test.sh
+++ b/test/fs/fs-test.sh
@@ -470,9 +470,9 @@ function check_results() {
# Check 1mb chunk write
grep -A3 "Test Case 11a " "$1" | \
egrep -q '1048576 bytes written|update journal'
-   pass_fail "TC11: 1MB write to $5 - write succeeded"
+   pass_fail "TC11: 1MB write to $3.w - write succeeded"
check_md5 "Test Case 11b " "$1" "$2" 1 \
-   "TC11: 1MB write to $5 - content verified"
+   "TC11: 1MB write to $3.w - content verified"
echo "** End $1"
 }
 
@@ -486,8 +486,7 @@ function test_fs_nonfs() {
OUT_FILE="${OUT}.$1.${fs}.out"
test_image $IMAGE $fs $SMALL_FILE $BIG_FILE $1 "" \
> ${OUT_FILE} 2>&1
-   check_results $OUT_FILE $MD5_FILE_FS $SMALL_FILE $BIG_FILE \
-   $WRITE_FILE
+   check_results $OUT_FILE $MD5_FILE_FS $SMALL_FILE $BIG_FILE
TOTAL_FAIL=$((TOTAL_FAIL + FAIL))
TOTAL_PASS=$((TOTAL_PASS + PASS))
echo "Summary: PASS: $PASS FAIL: $FAIL"
@@ -537,8 +536,7 @@ for fs in ext4 fat; do
sudo umount "$MOUNT_DIR"
rmdir "$MOUNT_DIR"
 
-   check_results $OUT_FILE $MD5_FILE_FS $SMALL_FILE $BIG_FILE \
-   $WRITE_FILE
+   check_results $OUT_FILE $MD5_FILE_FS $SMALL_FILE $BIG_FILE
TOTAL_FAIL=$((TOTAL_FAIL + FAIL))
TOTAL_PASS=$((TOTAL_PASS + PASS))
echo "Summary: PASS: $PASS FAIL: $FAIL"
-- 
2.10.0

___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


[U-Boot] [PATCH 4/4] cmd/fat: Do not crash on write when is not specified

2016-09-11 Thread Stefan Brüns
argc is checked, but is off by one. In case  is not specified,
create an empty file, which is identical to the ext4write behaviour.

Signed-off-by: Stefan Brüns <stefan.bru...@rwth-aachen.de>
---
 cmd/fat.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/cmd/fat.c b/cmd/fat.c
index 4e20746..ad1dc2a 100644
--- a/cmd/fat.c
+++ b/cmd/fat.c
@@ -126,7 +126,7 @@ static int do_fat_fswrite(cmd_tbl_t *cmdtp, int flag,
return 1;
}
addr = simple_strtoul(argv[3], NULL, 16);
-   count = simple_strtoul(argv[5], NULL, 16);
+   count = (argc <= 5) ? 0 : simple_strtoul(argv[5], NULL, 16);
 
buf = map_sysmem(addr, count);
ret = file_fat_write(argv[4], buf, 0, count, );
@@ -145,7 +145,7 @@ static int do_fat_fswrite(cmd_tbl_t *cmdtp, int flag,
 U_BOOT_CMD(
fatwrite,   6,  0,  do_fat_fswrite,
"write file into a dos filesystem",
-   " <dev[:part]>   \n"
+   " <dev[:part]>   []\n"
"- write file 'filename' from the address 'addr' in RAM\n"
"  to 'dev' on 'interface'"
 );
-- 
2.10.0

___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


[U-Boot] [PATCH 3/4] fs/fat: Correct description of determine_fatent function

2016-09-11 Thread Stefan Brüns
Current description does not match the function behaviour.

Signed-off-by: Stefan Brüns <stefan.bru...@rwth-aachen.de>
---
 fs/fat/fat_write.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/fs/fat/fat_write.c b/fs/fat/fat_write.c
index babe9c8..0583af3 100644
--- a/fs/fat/fat_write.c
+++ b/fs/fat/fat_write.c
@@ -528,7 +528,8 @@ static int set_fatent_value(fsdata *mydata, __u32 entry, 
__u32 entry_value)
 }
 
 /*
- * Determine the entry value at index 'entry' in a FAT (16/32) table
+ * Determine the next free cluster after 'entry' in a FAT (16/32) table
+ * and link it to 'entry'. EOC marker is not set on returned entry.
  */
 static __u32 determine_fatent(fsdata *mydata, __u32 entry)
 {
@@ -537,6 +538,7 @@ static __u32 determine_fatent(fsdata *mydata, __u32 entry)
while (1) {
next_fat = get_fatent_value(mydata, next_entry);
if (next_fat == 0) {
+   /* found free entry, link to entry */
set_fatent_value(mydata, entry, next_entry);
break;
}
-- 
2.10.0

___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


[U-Boot] [PATCH 2/4] fs/fat: Do not write unmodified fat entries to disk

2016-09-11 Thread Stefan Brüns
The code caches 6 sectors of the FAT. On FAT traversal, the old contents
needs to be flushed to disk, but only if any FAT entries had been modified.
Explicitly flag the buffer on modification.

Currently, creating a new file traverses the whole FAT up to the first
free cluster and rewrites the on-disk blocks.

Signed-off-by: Stefan Brüns <stefan.bru...@rwth-aachen.de>
---
 fs/fat/fat.c   |  1 +
 fs/fat/fat_write.c | 31 +++
 include/fat.h  |  1 +
 3 files changed, 21 insertions(+), 12 deletions(-)

diff --git a/fs/fat/fat.c b/fs/fat/fat.c
index 826bd85..df9f2b5 100644
--- a/fs/fat/fat.c
+++ b/fs/fat/fat.c
@@ -876,6 +876,7 @@ int do_fat_read_at(const char *filename, loff_t pos, void 
*buffer,
}
 
mydata->fatbufnum = -1;
+   mydata->fat_dirty = 0;
mydata->fatbuf = memalign(ARCH_DMA_MINALIGN, FATBUFSIZE);
if (mydata->fatbuf == NULL) {
debug("Error: allocating memory\n");
diff --git a/fs/fat/fat_write.c b/fs/fat/fat_write.c
index 961ccd8..babe9c8 100644
--- a/fs/fat/fat_write.c
+++ b/fs/fat/fat_write.c
@@ -104,13 +104,19 @@ static __u8 num_of_fats;
 /*
  * Write fat buffer into block device
  */
-static int flush_fat_buffer(fsdata *mydata)
+static int flush_dirty_fat_buffer(fsdata *mydata)
 {
int getsize = FATBUFBLOCKS;
__u32 fatlength = mydata->fatlength;
__u8 *bufptr = mydata->fatbuf;
__u32 startblock = mydata->fatbufnum * FATBUFBLOCKS;
 
+   debug("debug: evicting %d, dirty: %d\n", mydata->fatbufnum,
+ (int)mydata->fat_dirty);
+
+   if ((!mydata->fat_dirty) || (mydata->fatbufnum == -1))
+   return 0;
+
startblock += mydata->fat_sect;
 
if (getsize > fatlength)
@@ -130,6 +136,7 @@ static int flush_fat_buffer(fsdata *mydata)
return -1;
}
}
+   mydata->fat_dirty = 0;
 
return 0;
 }
@@ -186,10 +193,8 @@ static __u32 get_fatent_value(fsdata *mydata, __u32 entry)
startblock += mydata->fat_sect; /* Offset from start of disk */
 
/* Write back the fatbuf to the disk */
-   if (mydata->fatbufnum != -1) {
-   if (flush_fat_buffer(mydata) < 0)
-   return -1;
-   }
+   if (flush_dirty_fat_buffer(mydata) < 0)
+   return -1;
 
if (disk_read(startblock, getsize, bufptr) < 0) {
debug("Error reading FAT blocks\n");
@@ -494,10 +499,8 @@ static int set_fatent_value(fsdata *mydata, __u32 entry, 
__u32 entry_value)
if (getsize > fatlength)
getsize = fatlength;
 
-   if (mydata->fatbufnum != -1) {
-   if (flush_fat_buffer(mydata) < 0)
-   return -1;
-   }
+   if (flush_dirty_fat_buffer(mydata) < 0)
+   return -1;
 
if (disk_read(startblock, getsize, bufptr) < 0) {
debug("Error reading FAT blocks\n");
@@ -506,6 +509,9 @@ static int set_fatent_value(fsdata *mydata, __u32 entry, 
__u32 entry_value)
mydata->fatbufnum = bufnum;
}
 
+   /* Mark as dirty */
+   mydata->fat_dirty = 1;
+
/* Set the actual entry */
switch (mydata->fatsize) {
case 32:
@@ -645,7 +651,7 @@ static void flush_dir_table(fsdata *mydata, dir_entry 
**dentptr)
 
dir_curclust = dir_newclust;
 
-   if (flush_fat_buffer(mydata) < 0)
+   if (flush_dirty_fat_buffer(mydata) < 0)
return;
 
memset(get_dentfromdir_block, 0x00,
@@ -675,7 +681,7 @@ static int clear_fatent(fsdata *mydata, __u32 entry)
}
 
/* Flush fat buffer */
-   if (flush_fat_buffer(mydata) < 0)
+   if (flush_dirty_fat_buffer(mydata) < 0)
return -1;
 
return 0;
@@ -1011,6 +1017,7 @@ static int do_fat_write(const char *filename, void 
*buffer, loff_t size,
}
 
mydata->fatbufnum = -1;
+   mydata->fat_dirty = 0;
mydata->fatbuf = memalign(ARCH_DMA_MINALIGN, FATBUFSIZE);
if (mydata->fatbuf == NULL) {
debug("Error: allocating memory\n");
@@ -,7 +1118,7 @@ static int do_fat_write(const char *filename, void 
*buffer, loff_t size,
debug("attempt to write 0x%llx bytes\n", *actwrite);
 
/* Flush fat buffer */
-   ret = flush_fat_buffer(mydata);
+   ret = flush_dirty_fat_buffer(mydata);
if (ret) {
printf("Error: flush fat buffer\n");
goto exit;
diff --git a/include/fat.h b/include/fat.h
index 9d053e6..8ec91cd 100644
--- a/include/fat.h
+++ b/include/fat.h
@@ -169,6 +169,7 @@ typedef struct {
 

[U-Boot] [PATCH 1/4] fs/fat: Remove two statements without effect

2016-09-11 Thread Stefan Brüns
fatlength is a local variable which is no more used after the assignment.
s_name is not used in the function, save the strncpy.

Signed-off-by: Stefan Brüns <stefan.bru...@rwth-aachen.de>
---
 fs/fat/fat_write.c | 5 +
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/fs/fat/fat_write.c b/fs/fat/fat_write.c
index eb3a916..961ccd8 100644
--- a/fs/fat/fat_write.c
+++ b/fs/fat/fat_write.c
@@ -183,7 +183,6 @@ static __u32 get_fatent_value(fsdata *mydata, __u32 entry)
if (getsize > fatlength)
getsize = fatlength;
 
-   fatlength *= mydata->sect_size; /* We want it in bytes now */
startblock += mydata->fat_sect; /* Offset from start of disk */
 
/* Write back the fatbuf to the disk */
@@ -326,10 +325,8 @@ fill_dir_slot(fsdata *mydata, dir_entry **dentptr, const 
char *l_name)
dir_slot *slotptr = (dir_slot *)get_contents_vfatname_block;
__u8 counter = 0, checksum;
int idx = 0, ret;
-   char s_name[16];
 
-   /* Get short file name and checksum value */
-   strncpy(s_name, (*dentptr)->name, 16);
+   /* Get short file name checksum value */
checksum = mkcksum((*dentptr)->name, (*dentptr)->ext);
 
do {
-- 
2.10.0

___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


[U-Boot] [PATCH 0/4] Fat filesystem enhancements

2016-09-11 Thread Stefan Brüns
Start cleanup of fat filesystem.

Stefan Brüns (4):
  fs/fat: Remove two statements without effect
  fs/fat: Do not write unmodified fat entries to disk
  fs/fat: Correct description of determine_fatent function
  cmd/fat: Do not crash on write when  is not specified

 cmd/fat.c  |  4 ++--
 fs/fat/fat.c   |  1 +
 fs/fat/fat_write.c | 40 +++-
 include/fat.h  |  1 +
 4 files changed, 27 insertions(+), 19 deletions(-)

-- 
2.10.0

___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


[U-Boot] [PATCH 0/3] Enhance fs tests

2016-09-11 Thread Stefan Brüns
Test for two corner cases in ext4 directory traversal.

Stefan Brüns (3):
  test/fs: Restructure file path specification to allow some flexibility
  test/fs: Check ext4 behaviour if dirent is first entry in directory
block
  test/fs: Check writes using "." (same dir) relative path

 test/fs/fs-test.sh | 94 +-
 1 file changed, 58 insertions(+), 36 deletions(-)

-- 
2.10.0

___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


[U-Boot] [PATCH 1/3] test/fs: Restructure file path specification to allow some flexibility

2016-09-11 Thread Stefan Brüns
Instead of providing the full path, specify directory and filename
separately. This allows to specify intermediate directories, required
for some additional tests.

Signed-off-by: Stefan Brüns <stefan.bru...@rwth-aachen.de>
---
 test/fs/fs-test.sh | 56 +++---
 1 file changed, 20 insertions(+), 36 deletions(-)

diff --git a/test/fs/fs-test.sh b/test/fs/fs-test.sh
index 93679cb..12450ed 100755
--- a/test/fs/fs-test.sh
+++ b/test/fs/fs-test.sh
@@ -135,22 +135,6 @@ function create_image() {
fi
 }
 
-# 1st parameter is the FS type: fat/ext4
-# 2nd parameter is the name of small file
-# Returns filename which can be used for fat or ext4 for writing
-function fname_for_write() {
-   case $1 in
-   ext4)
-   # ext4 needs absolute path name of file
-   echo /${2}.w
-   ;;
-
-   *)
-   echo ${2}.w
-   ;;
-   esac
-}
-
 # 1st parameter is image file
 # 2nd parameter is file system type - fat/ext4
 # 3rd parameter is name of small file
@@ -166,11 +150,14 @@ function test_image() {
 
case "$2" in
fat)
+   FPATH=""
PREFIX="fat"
WRITE="write"
;;
 
ext4)
+   # ext4 needs absolute path
+   FPATH="/"
PREFIX="ext4"
WRITE="write"
;;
@@ -205,15 +192,12 @@ function test_image() {
 
esac
 
-   if [ -z "$6" ]; then
-   FILE_WRITE=`fname_for_write $2 $3`
-   FILE_SMALL=$3
-   FILE_BIG=$4
-   else
-   FILE_WRITE=$6/`fname_for_write $2 $3`
-   FILE_SMALL=$6/$3
-   FILE_BIG=$6/$4
+   if [ ! -z "$6" ]; then
+   FPATH=${6}/${FPATH}
fi
+   FILE_WRITE=${3}.w
+   FILE_SMALL=$3
+   FILE_BIG=$4
 
# In u-boot commands,  stands for host or hostfs
# hostfs maps to the host fs.
@@ -230,13 +214,13 @@ ${PREFIX}ls host${SUFFIX} $6
 # sb size hostfs - $3 for hostfs commands.
 # 1MB is 0x0010 
 # Test Case 2 - size of small file
-${PREFIX}size host${SUFFIX} $FILE_SMALL
+${PREFIX}size host${SUFFIX} ${FPATH}$FILE_SMALL
 printenv filesize
 setenv filesize
 
 # 2.5GB (1024*1024*2500) is 0x9C40 
 # Test Case 3 - size of big file
-${PREFIX}size host${SUFFIX} $FILE_BIG
+${PREFIX}size host${SUFFIX} ${FPATH}$FILE_BIG
 printenv filesize
 setenv filesize
 
@@ -245,14 +229,14 @@ setenv filesize
 # Last two parameters are size and offset.
 
 # Test Case 4a - Read full 1MB of small file
-${PREFIX}load host${SUFFIX} $addr $FILE_SMALL
+${PREFIX}load host${SUFFIX} $addr ${FPATH}$FILE_SMALL
 printenv filesize
 # Test Case 4b - Read full 1MB of small file
 md5sum $addr \$filesize
 setenv filesize
 
 # Test Case 5a - First 1MB of big file
-${PREFIX}load host${SUFFIX} $addr $FILE_BIG $length 0x0
+${PREFIX}load host${SUFFIX} $addr ${FPATH}$FILE_BIG $length 0x0
 printenv filesize
 # Test Case 5b - First 1MB of big file
 md5sum $addr \$filesize
@@ -260,7 +244,7 @@ setenv filesize
 
 # fails for ext as no offset support
 # Test Case 6a - Last 1MB of big file
-${PREFIX}load host${SUFFIX} $addr $FILE_BIG $length 0x9C30
+${PREFIX}load host${SUFFIX} $addr ${FPATH}$FILE_BIG $length 0x9C30
 printenv filesize
 # Test Case 6b - Last 1MB of big file
 md5sum $addr \$filesize
@@ -268,7 +252,7 @@ setenv filesize
 
 # fails for ext as no offset support
 # Test Case 7a - One from the last 1MB chunk of 2GB
-${PREFIX}load host${SUFFIX} $addr $FILE_BIG $length 0x7FF0
+${PREFIX}load host${SUFFIX} $addr ${FPATH}$FILE_BIG $length 0x7FF0
 printenv filesize
 # Test Case 7b - One from the last 1MB chunk of 2GB
 md5sum $addr \$filesize
@@ -276,7 +260,7 @@ setenv filesize
 
 # fails for ext as no offset support
 # Test Case 8a - One from the start 1MB chunk from 2GB
-${PREFIX}load host${SUFFIX} $addr $FILE_BIG $length 0x8000
+${PREFIX}load host${SUFFIX} $addr ${FPATH}$FILE_BIG $length 0x8000
 printenv filesize
 # Test Case 8b - One from the start 1MB chunk from 2GB
 md5sum $addr \$filesize
@@ -284,7 +268,7 @@ setenv filesize
 
 # fails for ext as no offset support
 # Test Case 9a - One 1MB chunk crossing the 2GB boundary
-${PREFIX}load host${SUFFIX} $addr $FILE_BIG $length 0x7FF8
+${PREFIX}load host${SUFFIX} $addr ${FPATH}$FILE_BIG $length 0x7FF8
 printenv filesize
 # Test Case 9b - One 1MB chunk crossing the 2GB boundary
 md5sum $addr \$filesize
@@ -292,17 +276,17 @@ setenv filesize
 
 # Generic failure case
 # Test Case 10 - 2MB chunk from the last 1MB of big file
-${PREFIX}load host${SUFFIX} $addr $FILE_BIG 0x0020 0x9C30
+${PREFIX}load host${SUFFIX} $addr ${FPATH}$FILE_BIG 0x0020 0x9C30
 printenv filesize
 #
 
 # Read 1MB from small file
-${PREFIX}load

[U-Boot] [PATCH 3/3] test/fs: Check writes using "." (same dir) relative path

2016-09-11 Thread Stefan Brüns
/ and /./ should reference the same file.

Signed-off-by: Stefan Brüns <stefan.bru...@rwth-aachen.de>
---
 test/fs/fs-test.sh | 27 +++
 1 file changed, 27 insertions(+)

diff --git a/test/fs/fs-test.sh b/test/fs/fs-test.sh
index cb2a765..46975ec 100755
--- a/test/fs/fs-test.sh
+++ b/test/fs/fs-test.sh
@@ -297,6 +297,23 @@ setenv filesize
 # The write should fail, but the lookup should work
 # Test Case 12 - Check directory traversal
 ${PREFIX}${WRITE} host${SUFFIX} $addr ${FPATH}. 0x10
+
+# Read 1MB from small file
+${PREFIX}load host${SUFFIX} $addr ${FPATH}$FILE_SMALL
+# Write it via "same directory", i.e. "." dirent
+# Test Case 13a - Check directory traversal
+${PREFIX}${WRITE} host${SUFFIX} $addr ${FPATH}./${FILE_WRITE}2 \$filesize
+mw.b $addr 00 100
+${PREFIX}load host${SUFFIX} $addr ${FPATH}./${FILE_WRITE}2
+# Test Case 13b - Check md5 of written to is same as the one read from
+md5sum $addr \$filesize
+setenv filesize
+mw.b $addr 00 100
+${PREFIX}load host${SUFFIX} $addr ${FPATH}${FILE_WRITE}2
+# Test Case 13c - Check md5 of written to is same as the one read from
+md5sum $addr \$filesize
+setenv filesize
+#
 reset
 
 EOF
@@ -482,6 +499,16 @@ function check_results() {
grep -A5 "Test Case 12 " "$1" | \
egrep -q 'Unable to write file'
pass_fail "TC12: 1MB write to . - write denied"
+
+   # Check directory traversal
+   grep -A6 "Test Case 13a " "$1" | \
+   egrep -q '1048576 bytes written|update journal'
+   pass_fail "TC13: 1MB write to ./$5 - write succeeded"
+   check_md5 "Test Case 13b " "$1" "$2" 1 \
+   "TC13: 1MB read from ./$5 - content verified"
+   check_md5 "Test Case 13c " "$1" "$2" 1 \
+   "TC13: 1MB read from $5 - content verified"
+
echo "** End $1"
 }
 
-- 
2.10.0

___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


[U-Boot] [PATCH 2/3] test/fs: Check ext4 behaviour if dirent is first entry in directory block

2016-09-11 Thread Stefan Brüns
This is a regression test for a crash happening if the first dirent
in the block matches. Code tried to access a predecessor entry which
does not exist.
The crash happened for any block, but "." is always the first entry in
the first directory block and thus easy to check for.

Signed-off-by: Stefan Brüns <stefan.bru...@rwth-aachen.de>
---
 test/fs/fs-test.sh | 11 +++
 1 file changed, 11 insertions(+)

diff --git a/test/fs/fs-test.sh b/test/fs/fs-test.sh
index 12450ed..cb2a765 100755
--- a/test/fs/fs-test.sh
+++ b/test/fs/fs-test.sh
@@ -291,6 +291,12 @@ ${PREFIX}load host${SUFFIX} $addr ${FPATH}$FILE_WRITE
 md5sum $addr \$filesize
 setenv filesize
 #
+
+# Next test case checks writing a file whose dirent
+# is the first in the block, which is always true for "."
+# The write should fail, but the lookup should work
+# Test Case 12 - Check directory traversal
+${PREFIX}${WRITE} host${SUFFIX} $addr ${FPATH}. 0x10
 reset
 
 EOF
@@ -471,6 +477,11 @@ function check_results() {
pass_fail "TC11: 1MB write to $5 - write succeeded"
check_md5 "Test Case 11b " "$1" "$2" 1 \
"TC11: 1MB write to $5 - content verified"
+
+   # Check lookup of 'dot' directory
+   grep -A5 "Test Case 12 " "$1" | \
+   egrep -q 'Unable to write file'
+   pass_fail "TC12: 1MB write to . - write denied"
echo "** End $1"
 }
 
-- 
2.10.0

___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


[U-Boot] [PATCH v5 07/16] ext4: Only update number of of unused inodes if GDT_CSUM feature is set

2016-09-05 Thread Stefan Brüns
e2fsck warns about "Group descriptor 0 marked uninitialized without
feature set."
The bg_itable_unused field is only defined if FEATURE_RO_COMPAT_GDT_CSUM
is set, and should be set (kept) zero otherwise.

Signed-off-by: Stefan Brüns <stefan.bru...@rwth-aachen.de>
Reviewed-by: Lukasz Majewski <l.majew...@samsung.com>
---
 fs/ext4/ext4_common.c | 14 +++---
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/fs/ext4/ext4_common.c b/fs/ext4/ext4_common.c
index e8e6c00..e58ba36 100644
--- a/fs/ext4/ext4_common.c
+++ b/fs/ext4/ext4_common.c
@@ -988,12 +988,13 @@ int ext4fs_get_new_inode_no(void)
if (!journal_buffer || !zero_buffer)
goto fail;
struct ext2_block_group *bgd = (struct ext2_block_group *)fs->gdtable;
+   int has_gdt_chksum = le32_to_cpu(fs->sb->feature_ro_compat) &
+   EXT4_FEATURE_RO_COMPAT_GDT_CSUM ? 1 : 0;
 
if (fs->first_pass_ibmap == 0) {
for (i = 0; i < fs->no_blkgrp; i++) {
if (bgd[i].free_inodes) {
-   if (bgd[i].bg_itable_unused !=
-   bgd[i].free_inodes)
+   if (has_gdt_chksum)
bgd[i].bg_itable_unused =
bgd[i].free_inodes;
if (le16_to_cpu(bgd[i].bg_flags) & 
EXT4_BG_INODE_UNINIT) {
@@ -1014,7 +1015,8 @@ int ext4fs_get_new_inode_no(void)
(i * inodes_per_grp);
fs->first_pass_ibmap++;
ext4fs_bg_free_inodes_dec([i]);
-   ext4fs_bg_itable_unused_dec([i]);
+   if (has_gdt_chksum)
+   ext4fs_bg_itable_unused_dec([i]);
ext4fs_sb_free_inodes_dec(fs->sb);
status = ext4fs_devread(

(lbaint_t)le32_to_cpu(bgd[i].inode_id) *
@@ -1069,12 +1071,10 @@ restart:
goto fail;
prev_inode_bitmap_index = ibmap_idx;
}
-   if (bgd[ibmap_idx].bg_itable_unused !=
-   bgd[ibmap_idx].free_inodes)
+   ext4fs_bg_free_inodes_dec([ibmap_idx]);
+   if (has_gdt_chksum)
bgd[ibmap_idx].bg_itable_unused =
bgd[ibmap_idx].free_inodes;
-   ext4fs_bg_free_inodes_dec([ibmap_idx]);
-   ext4fs_bg_itable_unused_dec([ibmap_idx]);
ext4fs_sb_free_inodes_dec(fs->sb);
goto success;
}
-- 
2.9.3

___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


[U-Boot] [PATCH v5 10/16] ext4: Avoid out-of-bounds access of block bitmap

2016-09-05 Thread Stefan Brüns
If the blocksize is 1024, count is initialized with 1. Incrementing count
by 8 will never match (count == fs->blksz * 8), and ptr may be
incremented beyond the buffer end if the bitmap is filled. Add the
startblock offset after the loop.

Remove the second loop, as only the first iteration will be done.

Signed-off-by: Stefan Brüns <stefan.bru...@rwth-aachen.de>
Reviewed-by: Lukasz Majewski <l.majew...@samsung.com>
---
 fs/ext4/ext4_common.c | 34 --
 1 file changed, 12 insertions(+), 22 deletions(-)

diff --git a/fs/ext4/ext4_common.c b/fs/ext4/ext4_common.c
index 8fc7559..72fc4af 100644
--- a/fs/ext4/ext4_common.c
+++ b/fs/ext4/ext4_common.c
@@ -163,18 +163,12 @@ static int _get_new_inode_no(unsigned char *buffer)
 
 static int _get_new_blk_no(unsigned char *buffer)
 {
-   unsigned char input;
-   int operand, status;
+   int operand;
int count = 0;
-   int j = 0;
+   int i;
unsigned char *ptr = buffer;
struct ext_filesystem *fs = get_fs();
 
-   if (fs->blksz != 1024)
-   count = 0;
-   else
-   count = 1;
-
while (*ptr == 255) {
ptr++;
count += 8;
@@ -182,21 +176,17 @@ static int _get_new_blk_no(unsigned char *buffer)
return -1;
}
 
-   for (j = 0; j < fs->blksz; j++) {
-   input = *ptr;
-   int i = 0;
-   while (i <= 7) {
-   operand = 1 << i;
-   status = input & operand;
-   if (status) {
-   i++;
-   count++;
-   } else {
-   *ptr |= operand;
-   return count;
-   }
+   if (fs->blksz == 1024)
+   count += 1;
+
+   for (i = 0; i <= 7; i++) {
+   operand = 1 << i;
+   if (*ptr & operand) {
+   count++;
+   } else {
+   *ptr |= operand;
+   return count;
}
-   ptr = ptr + 1;
}
 
return -1;
-- 
2.9.3

___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


[U-Boot] [PATCH v5 15/16] ext4: Correct block number handling, empty block vs. error code

2016-09-05 Thread Stefan Brüns
read_allocated block may return block number 0, which is just an indicator
a chunk of the file is not backed by a block, i.e. it is sparse.

During file deletions, just continue with the next logical block, for other
operations treat blocknumber <= 0 as an error.

For writes, blocknumber 0 should never happen, as U-Boot always allocates
blocks for the whole file.  Reading already handles this correctly, i.e. the
read buffer is 0-fillled.

Not treating block 0 as sparse block leads to FS corruption, e.g.
./sandbox/u-boot -c 'host bind 0 ./sandbox/test/fs/3GB.ext4.img ;
ext4write host 0 0 /2.5GB.file 1 '
The 2.5GB.file from the fs test is actually a sparse file.

Signed-off-by: Stefan Brüns <stefan.bru...@rwth-aachen.de>
---
 fs/ext4/ext4_common.c |  6 +++---
 fs/ext4/ext4_write.c  | 11 ++-
 2 files changed, 13 insertions(+), 4 deletions(-)

diff --git a/fs/ext4/ext4_common.c b/fs/ext4/ext4_common.c
index 72fc4af..a78b0b8 100644
--- a/fs/ext4/ext4_common.c
+++ b/fs/ext4/ext4_common.c
@@ -534,7 +534,7 @@ static int search_dir(struct ext2_inode *parent_inode, char 
*dirname)
/* get the block no allocated to a file */
for (blk_idx = 0; blk_idx < directory_blocks; blk_idx++) {
blknr = read_allocated_block(parent_inode, blk_idx);
-   if (blknr == 0)
+   if (blknr <= 0)
goto fail;
 
/* read the directory block */
@@ -828,7 +828,7 @@ int ext4fs_filename_unlink(char *filename)
/* read the block no allocated to a file */
for (blk_idx = 0; blk_idx < directory_blocks; blk_idx++) {
blknr = read_allocated_block(g_parent_inode, blk_idx);
-   if (blknr == 0)
+   if (blknr <= 0)
break;
inodeno = unlink_filename(filename, blknr);
if (inodeno != -1)
@@ -1590,7 +1590,7 @@ long int read_allocated_block(struct ext2_inode *inode, 
int fileblock)
if (status == 0) {
printf("** SI ext2fs read block (indir 1)"
"failed. **\n");
-   return 0;
+   return -1;
}
ext4fs_indir1_blkno =
le32_to_cpu(inode->b.blocks.
diff --git a/fs/ext4/ext4_write.c b/fs/ext4/ext4_write.c
index 20005f5..b3ea07b 100644
--- a/fs/ext4/ext4_write.c
+++ b/fs/ext4/ext4_write.c
@@ -461,6 +461,10 @@ static int ext4fs_delete_file(int inodeno)
/* release data blocks */
for (i = 0; i < no_blocks; i++) {
blknr = read_allocated_block(, i);
+   if (blknr == 0)
+   continue;
+   if (blknr < 0)
+   goto fail;
bg_idx = blknr / blk_per_grp;
if (fs->blksz == 1024) {
remainder = blknr % blk_per_grp;
@@ -718,6 +722,10 @@ void ext4fs_deinit(void)
fs->curr_blkno = 0;
 }
 
+/*
+ * Write data to filesystem blocks. Uses same optimization for
+ * contigous sectors as ext4fs_read_file
+ */
 static int ext4fs_write_file(struct ext2_inode *file_inode,
 int pos, unsigned int len, char *buf)
 {
@@ -744,7 +752,7 @@ static int ext4fs_write_file(struct ext2_inode *file_inode,
int blockend = fs->blksz;
int skipfirst = 0;
blknr = read_allocated_block(file_inode, i);
-   if (blknr < 0)
+   if (blknr <= 0)
return -1;
 
blknr = blknr << log2_fs_blocksize;
@@ -910,6 +918,7 @@ int ext4fs_write(const char *fname, unsigned char *buffer,
/* copy the file content into data blocks */
if (ext4fs_write_file(file_inode, 0, sizebytes, (char *)buffer) == -1) {
printf("Error in copying content\n");
+   /* FIXME: Deallocate data blocks */
goto fail;
}
ibmap_idx = parent_inodeno / 
le32_to_cpu(ext4fs_root->sblock.inodes_per_group);
-- 
2.9.3

___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


[U-Boot] [PATCH v5 14/16] ext4: remove duplicated block release code for extents

2016-09-05 Thread Stefan Brüns
The data blocks are identical for files using traditional direct/indirect
block allocation scheme and extent trees, thus this code part can be
common. Only the code to deallocate the indirect blocks to record the
used blocks has to be seperate, respectively the code to release extent
tree index blocks.

Actually the code to release the extent tree index blocks is still missing,
but at least add a FIXME at the appropriate place.

Signed-off-by: Stefan Brüns <stefan.bru...@rwth-aachen.de>
---
 fs/ext4/ext4_write.c | 110 ---
 1 file changed, 33 insertions(+), 77 deletions(-)

diff --git a/fs/ext4/ext4_write.c b/fs/ext4/ext4_write.c
index 5b518ed..20005f5 100644
--- a/fs/ext4/ext4_write.c
+++ b/fs/ext4/ext4_write.c
@@ -447,92 +447,48 @@ static int ext4fs_delete_file(int inodeno)
no_blocks++;
 
if (le32_to_cpu(inode.flags) & EXT4_EXTENTS_FL) {
-   struct ext2fs_node *node_inode =
-   zalloc(sizeof(struct ext2fs_node));
-   if (!node_inode)
-   goto fail;
-   node_inode->data = ext4fs_root;
-   node_inode->ino = inodeno;
-   node_inode->inode_read = 0;
-   memcpy(&(node_inode->inode), , sizeof(struct ext2_inode));
-
-   for (i = 0; i < no_blocks; i++) {
-   blknr = read_allocated_block(&(node_inode->inode), i);
-   bg_idx = blknr / blk_per_grp;
-   if (fs->blksz == 1024) {
-   remainder = blknr % blk_per_grp;
-   if (!remainder)
-   bg_idx--;
-   }
-   ext4fs_reset_block_bmap(blknr, fs->blk_bmaps[bg_idx],
-   bg_idx);
-   debug("EXT4_EXTENTS Block releasing %ld: %d\n",
- blknr, bg_idx);
-
-   ext4fs_bg_free_blocks_inc([bg_idx]);
-   ext4fs_sb_free_blocks_inc(fs->sb);
-
-   /* journal backup */
-   if (prev_bg_bmap_idx != bg_idx) {
-   status =
-   ext4fs_devread(
-  
(lbaint_t)le32_to_cpu(bgd[bg_idx].block_id) *
-  fs->sect_perblk, 0,
-  fs->blksz, journal_buffer);
-   if (status == 0)
-   goto fail;
-   if (ext4fs_log_journal(journal_buffer,
-   
le32_to_cpu(bgd[bg_idx].block_id)))
-   goto fail;
-   prev_bg_bmap_idx = bg_idx;
-   }
-   }
-   if (node_inode) {
-   free(node_inode);
-   node_inode = NULL;
-   }
+   /* FIXME delete extent index blocks, i.e. eh_depth >= 1 */
+   struct ext4_extent_header *eh =
+   (struct ext4_extent_header *)
+   inode.b.blocks.dir_blocks;
+   debug("del: dep=%d entries=%d\n", eh->eh_depth, eh->eh_entries);
} else {
-
delete_single_indirect_block();
delete_double_indirect_block();
delete_triple_indirect_block();
+   }
 
-   /* read the block no allocated to a file */
-   no_blocks = le32_to_cpu(inode.size) / fs->blksz;
-   if (le32_to_cpu(inode.size) % fs->blksz)
-   no_blocks++;
-   for (i = 0; i < no_blocks; i++) {
-   blknr = read_allocated_block(, i);
-   bg_idx = blknr / blk_per_grp;
-   if (fs->blksz == 1024) {
-   remainder = blknr % blk_per_grp;
-   if (!remainder)
-   bg_idx--;
-   }
-   ext4fs_reset_block_bmap(blknr, fs->blk_bmaps[bg_idx],
-   bg_idx);
-   debug("ActualB releasing %ld: %d\n", blknr, bg_idx);
+   /* release data blocks */
+   for (i = 0; i < no_blocks; i++) {
+   blknr = read_allocated_block(, i);
+   bg_idx = blknr / blk_per_grp;
+   if (fs->blksz == 1024) {
+   remainder = blknr % blk_per_grp;
+   if (!remainder)
+   bg_idx--;
+   }
+   ext4fs_reset_block_bmap(blknr, fs->blk_bmaps[bg_idx],
+   

[U-Boot] [PATCH v5 03/16] ext4: Do not crash when trying to grow a directory using extents

2016-09-05 Thread Stefan Brüns
The following command crashes u-boot:
./sandbox/u-boot -c 'i=0; host bind 0 ./sandbox/test/fs/3GB.ext4.img ;
  while test $i -lt 200 ; do echo $i; setexpr i $i + 1;
  ext4write host 0 0 /foobar${i} 0; done'

Previously, the code updated the direct_block even for extents, and
fortunately crashed before pushing garbage to the disk.

Signed-off-by: Stefan Brüns <stefan.bru...@rwth-aachen.de>
Reviewed-by: Lukasz Majewski <l.majew...@samsung.com>
---
 fs/ext4/ext4_common.c | 7 ++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/fs/ext4/ext4_common.c b/fs/ext4/ext4_common.c
index 5799bee..dff03fe 100644
--- a/fs/ext4/ext4_common.c
+++ b/fs/ext4/ext4_common.c
@@ -453,8 +453,13 @@ restart:
sizeof(struct ext2_dirent) + padding_factor;
if ((fs->blksz - totalbytes - last_entry_dirlen) <
new_entry_byte_reqd) {
-   printf("1st Block Full:Allocate new block\n");
+   printf("Last Block Full:Allocate new block\n");
 
+   if (le32_to_cpu(g_parent_inode->flags) &
+   EXT4_EXTENTS_FL) {
+   printf("Directory uses extents\n");
+   goto fail;
+   }
if (direct_blk_idx == INDIRECT_BLOCKS - 1) {
printf("Directory exceeds limit\n");
goto fail;
-- 
2.9.3

___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


[U-Boot] [PATCH v5 05/16] ext4: Avoid corruption of directories with hash tree indexes

2016-09-05 Thread Stefan Brüns
While directories can be read using the old linear scan method, adding a
new file would require updating the index tree (alternatively, the whole
tree could be removed).

Signed-off-by: Stefan Brüns <stefan.bru...@rwth-aachen.de>
Reviewed-by: Lukasz Majewski <l.majew...@samsung.com>
---
 fs/ext4/ext4_write.c | 5 +
 include/ext4fs.h | 1 +
 2 files changed, 6 insertions(+)

diff --git a/fs/ext4/ext4_write.c b/fs/ext4/ext4_write.c
index 42abd8d..50c8415 100644
--- a/fs/ext4/ext4_write.c
+++ b/fs/ext4/ext4_write.c
@@ -881,6 +881,11 @@ int ext4fs_write(const char *fname, unsigned char *buffer,
goto fail;
if (ext4fs_iget(parent_inodeno, g_parent_inode))
goto fail;
+   /* do not mess up a directory using hash trees */
+   if (le32_to_cpu(g_parent_inode->flags) & EXT4_INDEX_FL) {
+   printf("hash tree directory\n");
+   goto fail;
+   }
/* check if the filename is already present in root */
existing_file_inodeno = ext4fs_filename_unlink(filename);
if (existing_file_inodeno != -1) {
diff --git a/include/ext4fs.h b/include/ext4fs.h
index e3f6216..6e31c73 100644
--- a/include/ext4fs.h
+++ b/include/ext4fs.h
@@ -28,6 +28,7 @@
 #define __EXT4__
 #include 
 
+#define EXT4_INDEX_FL  0x1000 /* Inode uses hash tree index */
 #define EXT4_EXTENTS_FL0x0008 /* Inode uses extents */
 #define EXT4_EXT_MAGIC 0xf30a
 #define EXT4_FEATURE_RO_COMPAT_GDT_CSUM0x0010
-- 
2.9.3

___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


[U-Boot] [PATCH v5 13/16] ext4: initialize full inode for inodes bigger than 128 bytes

2016-09-05 Thread Stefan Brüns
Make sure the the extra_isize field (offset 128) is initialized to 0, to
mark any extra data as invalid.

Signed-off-by: Stefan Brüns <stefan.bru...@rwth-aachen.de>
Reviewed-by: Lukasz Majewski <l.majew...@samsung.com>
---
 fs/ext4/ext4_write.c | 10 --
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/fs/ext4/ext4_write.c b/fs/ext4/ext4_write.c
index 81a750b..5b518ed 100644
--- a/fs/ext4/ext4_write.c
+++ b/fs/ext4/ext4_write.c
@@ -560,7 +560,7 @@ static int ext4fs_delete_file(int inodeno)
 
read_buffer = read_buffer + blkoff;
inode_buffer = (struct ext2_inode *)read_buffer;
-   memset(inode_buffer, '\0', sizeof(struct ext2_inode));
+   memset(inode_buffer, '\0', fs->inodesz);
 
/* write the inode to original position in inode table */
if (ext4fs_put_metadata(start_block_address, blkno))
@@ -866,7 +866,7 @@ int ext4fs_write(const char *fname, unsigned char *buffer,
ALLOC_CACHE_ALIGN_BUFFER(char, filename, 256);
memset(filename, 0x00, 256);
 
-   g_parent_inode = zalloc(sizeof(struct ext2_inode));
+   g_parent_inode = zalloc(fs->inodesz);
if (!g_parent_inode)
goto fail;
 
@@ -969,8 +969,7 @@ int ext4fs_write(const char *fname, unsigned char *buffer,
if (ext4fs_log_journal(temp_ptr, parent_itable_blkno))
goto fail;
 
-   memcpy(temp_ptr + blkoff, g_parent_inode,
-   sizeof(struct ext2_inode));
+   memcpy(temp_ptr + blkoff, g_parent_inode, fs->inodesz);
if (ext4fs_put_metadata(temp_ptr, parent_itable_blkno))
goto fail;
} else {
@@ -978,8 +977,7 @@ int ext4fs_write(const char *fname, unsigned char *buffer,
 * If parent and child fall in same inode table block
 * both should be kept in 1 buffer
 */
-   memcpy(temp_ptr + blkoff, g_parent_inode,
-  sizeof(struct ext2_inode));
+   memcpy(temp_ptr + blkoff, g_parent_inode, fs->inodesz);
gd_index--;
if (ext4fs_put_metadata(temp_ptr, itable_blkno))
goto fail;
-- 
2.9.3

___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


[U-Boot] [PATCH v5 04/16] ext4: Scan all directory blocks for space when inserting a new entry

2016-09-05 Thread Stefan Brüns
Previously, only the last directory block was scanned for available space.
Instead, scan all blocks back to front, and if no sufficient space is
found, eventually append a new block.
Blocks are only appended if the directory does not use extents or the new
block would require insertion of indirect blocks, as the old code does.

Signed-off-by: Stefan Brüns <stefan.bru...@rwth-aachen.de>
Reviewed-by: Lukasz Majewski <l.majew...@samsung.com>
---
 fs/ext4/ext4_common.c | 74 +--
 1 file changed, 30 insertions(+), 44 deletions(-)

diff --git a/fs/ext4/ext4_common.c b/fs/ext4/ext4_common.c
index dff03fe..062ea93 100644
--- a/fs/ext4/ext4_common.c
+++ b/fs/ext4/ext4_common.c
@@ -370,14 +370,10 @@ int ext4fs_update_parent_dentry(char *filename, int 
file_type)
 {
unsigned int *zero_buffer = NULL;
char *root_first_block_buffer = NULL;
-   int direct_blk_idx;
-   long int root_blknr;
+   int blk_idx;
long int first_block_no_of_root = 0;
-   long int previous_blknr = -1;
int totalbytes = 0;
-   short int padding_factor = 0;
unsigned int new_entry_byte_reqd;
-   unsigned int last_entry_dirlen;
int sizeof_void_space = 0;
int templength = 0;
int inodeno = -1;
@@ -389,6 +385,7 @@ int ext4fs_update_parent_dentry(char *filename, int 
file_type)
uint32_t new_blk_no;
uint32_t new_size;
uint32_t new_blockcnt;
+   uint32_t directory_blocks;
 
zero_buffer = zalloc(fs->blksz);
if (!zero_buffer) {
@@ -401,19 +398,18 @@ int ext4fs_update_parent_dentry(char *filename, int 
file_type)
printf("No Memory\n");
return -1;
}
+   new_entry_byte_reqd = ROUND(strlen(filename) +
+   sizeof(struct ext2_dirent), 4);
 restart:
+   directory_blocks = le32_to_cpu(g_parent_inode->size) >>
+   LOG2_BLOCK_SIZE(ext4fs_root);
+   blk_idx = directory_blocks - 1;
 
+restart_read:
/* read the block no allocated to a file */
-   for (direct_blk_idx = 0; direct_blk_idx < INDIRECT_BLOCKS;
-direct_blk_idx++) {
-   root_blknr = read_allocated_block(g_parent_inode,
- direct_blk_idx);
-   if (root_blknr == 0) {
-   first_block_no_of_root = previous_blknr;
-   break;
-   }
-   previous_blknr = root_blknr;
-   }
+   first_block_no_of_root = read_allocated_block(g_parent_inode, blk_idx);
+   if (first_block_no_of_root <= 0)
+   goto fail;
 
status = ext4fs_devread((lbaint_t)first_block_no_of_root
* fs->sect_perblk,
@@ -425,42 +421,33 @@ restart:
goto fail;
dir = (struct ext2_dirent *)root_first_block_buffer;
totalbytes = 0;
+
while (le16_to_cpu(dir->direntlen) > 0) {
-   /*
-* blocksize-totalbytes because last directory length
-* i.e. dir->direntlen is free availble space in the
-* block that means  it is a last entry of directory
-* entry
-*/
+   unsigned short used_len = ROUND(dir->namelen +
+   sizeof(struct ext2_dirent), 4);
 
-   /* traversing the each directory entry */
+   /* last entry of block */
if (fs->blksz - totalbytes == le16_to_cpu(dir->direntlen)) {
-   if (strlen(filename) % 4 != 0)
-   padding_factor = 4 - (strlen(filename) % 4);
-
-   new_entry_byte_reqd = strlen(filename) +
-   sizeof(struct ext2_dirent) + padding_factor;
-   padding_factor = 0;
-   /*
-* update last directory entry length to its
-* length because we are creating new directory
-* entry
-*/
-   if (dir->namelen % 4 != 0)
-   padding_factor = 4 - (dir->namelen % 4);
 
-   last_entry_dirlen = dir->namelen +
-   sizeof(struct ext2_dirent) + padding_factor;
-   if ((fs->blksz - totalbytes - last_entry_dirlen) <
-   new_entry_byte_reqd) {
-   printf("Last Block Full:Allocate new block\n");
+   /* check if new entry fits */
+   if ((used_len + new_entry_byte_reqd) <=
+   le16_to_cpu(dir->direntlen)) {
+   dir->direntlen = cpu_to_le16(used_len);
+   break;
+   } else {
+

[U-Boot] [PATCH v5 16/16] ext4: Fix memory leak of journal buffer if block is updated multiple times

2016-09-05 Thread Stefan Brüns
If the same block is updated multiple times in a row during a single
file system operation, gd_index is decremented to use the same journal
entry again. Avoid loosing the already allocated buffer.

Signed-off-by: Stefan Brüns <stefan.bru...@rwth-aachen.de>
---
 fs/ext4/ext4_journal.c | 6 +-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/fs/ext4/ext4_journal.c b/fs/ext4/ext4_journal.c
index cf14049..5a25be4 100644
--- a/fs/ext4/ext4_journal.c
+++ b/fs/ext4/ext4_journal.c
@@ -190,7 +190,11 @@ int ext4fs_put_metadata(char *metadata_buffer, uint32_t 
blknr)
printf("Invalid input arguments %s\n", __func__);
return -EINVAL;
}
-   dirty_block_ptr[gd_index]->buf = zalloc(fs->blksz);
+   if (dirty_block_ptr[gd_index]->buf)
+   assert(dirty_block_ptr[gd_index]->blknr == blknr);
+   else
+   dirty_block_ptr[gd_index]->buf = zalloc(fs->blksz);
+
if (!dirty_block_ptr[gd_index]->buf)
return -ENOMEM;
memcpy(dirty_block_ptr[gd_index]->buf, metadata_buffer, fs->blksz);
-- 
2.9.3

___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


[U-Boot] [PATCH v5 00/16] Fix several possible crashes/corruptions in ext4

2016-09-05 Thread Stefan Brüns
The U-Boot ext4 support has some bugs which either cause U-Boot crashes
or lead to filesystem corruption.

This series goes on top of the endian patch series by Michael Walle.
It has been rebased against v4 of the series.

The first 13 patches have already been reviewed, last 3 patches are
new. Revieved-by has been added as appropriate.


Stefan Brüns (16):
  ext4: fix possible crash on directory traversal, ignore deleted entries
  ext4: propagate error if creation of directory entry fails
  ext4: Do not crash when trying to grow a directory using extents
  ext4: Scan all directory blocks for space when inserting a new entry
  ext4: Avoid corruption of directories with hash tree indexes
  ext4: Scan all directory blocks when looking up an entry
  ext4: Only update number of of unused inodes if GDT_CSUM feature is set
  ext4: Do not clear zalloc'ed buffers a second time
  ext4: After completely filled group, scan next group from the beginning
  ext4: Avoid out-of-bounds access of block bitmap
  ext4: Fix memory leak in case of failure
  ext4: Use correct value for inode size even on revision 0 filesystems
  ext4: initialize full inode for inodes bigger than 128 bytes
  ext4: remove duplicated block release code for extents
  ext4: Correct block number handling, empty block vs. error code
  ext4: Fix memory leak of journal buffer if block is updated multiple times

 fs/ext4/ext4_common.c  | 288 +
 fs/ext4/ext4_common.h  |   2 +-
 fs/ext4/ext4_journal.c |   6 +-
 fs/ext4/ext4_write.c   | 147 ++---
 include/ext4fs.h   |   3 +-
 include/ext_common.h   |   2 -
 6 files changed, 190 insertions(+), 258 deletions(-)

v2:
  Updated:
  ext4: fix possible crash on directory traversal, ignore deleted entries
- Fix bad filename compare on delete, used substring only

v3:
  Added:
  ext4: Scan all directory blocks for space when inserting a new entry
  ext4: Only update number of of unused inodes if GDT_CSUM feature is set
  ext4: Do not clear zalloc'ed buffers a second time
  ext4: After completely filled group, scan next group from the beginning
  ext4: Avoid out-of-bounds access of block bitmap
  ext4: Fix memory leak in case of failure
  ext4: Use correct value for inode size even on revision 0 filesystems
  ext4: initialize full inode for inodes bigger than 128 bytes
  ext4: remove duplicated block release code for extents

  Updated:
  ext4: Scan all directory blocks when looking up an entry
- use parent_inode instead of g_parent_inode when determining directory size

v4:
  Updated:
  ext4: Scan all directory blocks when looking up an entry
- fix directory scan, direntname was advanced by offset instead of direntlen
  Problem reported by Thomas Schaefer <thomas.schae...@kontron.com>

v5:
  Added:
  ext4: remove duplicated block release code for extents
  ext4: Correct block number handling, empty block vs. error code
  ext4: Fix memory leak of journal buffer if block is updated multiple times

  Updated:
  ext4: initialize full inode for inodes bigger than 128 bytes
- fix memory corruption if sizeof(struct ext2_inode) != fs->inodesz
  Problem reported by Thomas Schaefer <thomas.schae...@kontron.com>

-- 
2.9.3

___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


[U-Boot] [PATCH v5 09/16] ext4: After completely filled group, scan next group from the beginning

2016-09-05 Thread Stefan Brüns
The last free block of a block group may be in its middle. After it has
been allocated, the next block group should be scanned from its beginning.

The following command triggers the bad behaviour (on a blocksize 1024 fs):

./sandbox/u-boot -c 'i=0; host bind 0 ./disk.raw ;
while test $i -lt 260 ; do echo $i; setexpr i $i + 1;
ext4write host 0:2 0 /X${i} 0x1450; done ;
ext4write host 0:2 0 /X240 0x2000 ; '

When 'X240' is extended from 5200 byte to 8192 byte, the new blocks should
start from the first free block (8811), but it uses the blocks 8098-8103
and 16296-16297 -- 8103 + 1 + 8192 = 16296. This can be shown with
debugfs, commands 'ffb' and 'stat X240'.

Signed-off-by: Stefan Brüns <stefan.bru...@rwth-aachen.de>
Reviewed-by: Lukasz Majewski <l.majew...@samsung.com>
---
 fs/ext4/ext4_common.c | 8 +---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/fs/ext4/ext4_common.c b/fs/ext4/ext4_common.c
index 539d622..8fc7559 100644
--- a/fs/ext4/ext4_common.c
+++ b/fs/ext4/ext4_common.c
@@ -903,8 +903,8 @@ uint32_t ext4fs_get_new_blk_no(void)
 
goto fail;
} else {
-restart:
fs->curr_blkno++;
+restart:
/* get the blockbitmap index respective to blockno */
bg_idx = fs->curr_blkno / blk_per_grp;
if (fs->blksz == 1024) {
@@ -922,8 +922,9 @@ restart:
 
if (bgd[bg_idx].free_blocks == 0) {
debug("block group %u is full. Skipping\n", bg_idx);
-   fs->curr_blkno = fs->curr_blkno + blk_per_grp;
-   fs->curr_blkno--;
+   fs->curr_blkno = (bg_idx + 1) * blk_per_grp;
+   if (fs->blksz == 1024)
+   fs->curr_blkno += 1;
goto restart;
}
 
@@ -940,6 +941,7 @@ restart:
   bg_idx) != 0) {
debug("going for restart for the block no %ld %u\n",
  fs->curr_blkno, bg_idx);
+   fs->curr_blkno++;
goto restart;
}
 
-- 
2.9.3

___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


[U-Boot] [PATCH v5 11/16] ext4: Fix memory leak in case of failure

2016-09-05 Thread Stefan Brüns
temp_ptr should always be freed, even if the function is left via
goto fail.

Signed-off-by: Stefan Brüns <stefan.bru...@rwth-aachen.de>
Reviewed-by: Lukasz Majewski <l.majew...@samsung.com>
---
 fs/ext4/ext4_write.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/fs/ext4/ext4_write.c b/fs/ext4/ext4_write.c
index 50c8415..5e208ef 100644
--- a/fs/ext4/ext4_write.c
+++ b/fs/ext4/ext4_write.c
@@ -974,7 +974,6 @@ int ext4fs_write(const char *fname, unsigned char *buffer,
sizeof(struct ext2_inode));
if (ext4fs_put_metadata(temp_ptr, parent_itable_blkno))
goto fail;
-   free(temp_ptr);
} else {
/*
 * If parent and child fall in same inode table block
@@ -985,7 +984,6 @@ int ext4fs_write(const char *fname, unsigned char *buffer,
gd_index--;
if (ext4fs_put_metadata(temp_ptr, itable_blkno))
goto fail;
-   free(temp_ptr);
}
ext4fs_update();
ext4fs_deinit();
@@ -996,6 +994,7 @@ int ext4fs_write(const char *fname, unsigned char *buffer,
fs->curr_inode_no = 0;
free(inode_buffer);
free(g_parent_inode);
+   free(temp_ptr);
g_parent_inode = NULL;
 
return 0;
@@ -1003,6 +1002,7 @@ fail:
ext4fs_deinit();
free(inode_buffer);
free(g_parent_inode);
+   free(temp_ptr);
g_parent_inode = NULL;
 
return -1;
-- 
2.9.3

___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


[U-Boot] [PATCH v5 08/16] ext4: Do not clear zalloc'ed buffers a second time

2016-09-05 Thread Stefan Brüns
zero_buffer is never written, thus clearing it is pointless.
journal_buffer is completely initialized by ext4fs_devread (or in case
of failure, not used).

Signed-off-by: Stefan Brüns <stefan.bru...@rwth-aachen.de>
Reviewed-by: Lukasz Majewski <l.majew...@samsung.com>
---
 fs/ext4/ext4_common.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/fs/ext4/ext4_common.c b/fs/ext4/ext4_common.c
index e58ba36..539d622 100644
--- a/fs/ext4/ext4_common.c
+++ b/fs/ext4/ext4_common.c
@@ -929,7 +929,6 @@ restart:
 
if (le16_to_cpu(bgd[bg_idx].bg_flags) & EXT4_BG_BLOCK_UNINIT) {
uint16_t new_flags;
-   memset(zero_buffer, '\0', fs->blksz);
put_ext4((uint64_t)le32_to_cpu(bgd[bg_idx].block_id) * 
fs->blksz,
 zero_buffer, fs->blksz);
memcpy(fs->blk_bmaps[bg_idx], zero_buffer, fs->blksz);
@@ -946,7 +945,6 @@ restart:
 
/* journal backup */
if (prev_bg_bitmap_index != bg_idx) {
-   memset(journal_buffer, '\0', fs->blksz);
status = ext4fs_devread(

(lbaint_t)le32_to_cpu(bgd[bg_idx].block_id)
* fs->sect_perblk,
@@ -1040,7 +1038,6 @@ restart:
ibmap_idx = fs->curr_inode_no / inodes_per_grp;
if (le16_to_cpu(bgd[ibmap_idx].bg_flags) & 
EXT4_BG_INODE_UNINIT) {
int new_flags;
-   memset(zero_buffer, '\0', fs->blksz);
put_ext4((uint64_t)le32_to_cpu(bgd[ibmap_idx].inode_id) 
* fs->blksz,
 zero_buffer, fs->blksz);
new_flags = le16_to_cpu(bgd[ibmap_idx].bg_flags) & 
~EXT4_BG_INODE_UNINIT;
-- 
2.9.3

___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


  1   2   >