Re: [U-Boot] [PATCH v2 2/8] fs/fat: introduce new director iterators
On Sat, Sep 9, 2017 at 12:55 AM, Simon Glass wrote: > Hi Rob, > > On 5 September 2017 at 03:54, Rob Clark wrote: >> On Tue, Sep 5, 2017 at 4:56 AM, Simon Glass wrote: >>> Hi Rob, >>> >>> On 3 September 2017 at 00:37, Rob Clark wrote: Untangle directory traversal into a simple iterator, to replace the existing multi-purpose do_fat_read_at() + get_dentfromdir(). Signed-off-by: Rob Clark --- fs/fat/fat.c | 326 +++ 1 file changed, 326 insertions(+) diff --git a/fs/fat/fat.c b/fs/fat/fat.c index e1c0a15dc7..c72d6ca931 100644 --- a/fs/fat/fat.c +++ b/fs/fat/fat.c @@ -1245,6 +1245,332 @@ exit: return ret; } + +/* + * Directory iterator, to simplify filesystem traversal + */ + +typedef struct { >>> >>> Please avoid using a typedef here. It seems like it could just be a struct. >> >> I'm typically not a fan of 'typedef struct' but that seems to be the >> style that fs/fat code was already using, and "when in Rome..." > > Sure, but let's move to Venice as it is less dusty. > I'm not a huge fan of mixing styles.. but what I'd propose instead is this: It turns out fat_write.c needs a lot of work for SCT too (ability to write files in subdirectories, and write files w/ !=0 offset), so that we can actually see the test results.. and before converting write paths to use the new directory iterator, I was considering re-organizing the code a bit, ie. move directory traversal code to fs/fat/dir.c or util.c, move most of include/fat.h into a private header, dropping the #include "fat.c" hack, etc. That would be a good time for flag-day cleanups like untypedef'ifying and perhaps cleaning up all the #define macros that implicitly depend on having a 'mydata' var. So I'd suggest to leave it as-is for now, and change things to 'struct foo' as part of the re-org. That leaves FS_DIR in the later readdir patch.. I could change that to 'struct fs_dir_stream'. That makes it not match the posix API it is modelled after as closely, but maybe that is ok. BR, -R ___ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot
[U-Boot] [PATCH v2 0/5] vsprintf and short-wchar
This patchset enables -fshort-wchar and adds support to vsprintf (%ls), along with GUID printing. Both things needed by efi_loader. Unlike the previous version of the patchset, which had a kconfig option selected by efi_loader to enable -fshort-wchar, and at Tom's suggestion, this patchset unconditionally switches to -fshort-wchar. Note that this patchset and the fs_readdir patchset (which I'll resend today) can be applied in either order. But both are dependencies for the stack of efi_loader patches to make normal distro boot work (shim/ fallback and upstream grub being able to locate it's grub.cfg properly). So either these could go before pulling efi-next or possibly have multiple efi-next pull requests so Heinrich's efi_loader patches can go first. Rob Clark (5): kbuild: Enable -fshort-wchar lib: add some utf16 handling helpers vsprintf.c: add UTF-16 string (%ls) support vsprintf.c: add GUID printing examples: add fallback memcpy Makefile | 1 + examples/api/Makefile| 2 + examples/api/glue.c | 12 + include/charset.h| 65 include/config_fallbacks.h | 1 + lib/Makefile | 1 + lib/charset.c| 101 +++ lib/efi_loader/efi_console.c | 17 ++-- lib/vsprintf.c | 76 ++-- 9 files changed, 258 insertions(+), 18 deletions(-) create mode 100644 include/charset.h create mode 100644 lib/charset.c -- 2.13.5 ___ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot
[U-Boot] [PATCH v2 1/5] kbuild: Enable -fshort-wchar
EFI_LOADER really wants UTF-16 strings (ie. %ls and L"string" are 16bit chars instead of 32bit chars). But rather than enabling -fshort-wchar conditionally if EFI_LOADER is enabled, it was deemed preferrable to globally switch. Signed-off-by: Rob Clark --- Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile b/Makefile index 5bb3b09115..d635de12ab 100644 --- a/Makefile +++ b/Makefile @@ -360,6 +360,7 @@ KBUILD_CPPFLAGS := -D__KERNEL__ -D__UBOOT__ KBUILD_CFLAGS := -Wall -Wstrict-prototypes \ -Wno-format-security \ -fno-builtin -ffreestanding +KBUILD_CFLAGS += -fshort-wchar KBUILD_AFLAGS := -D__ASSEMBLY__ # Read UBOOTRELEASE from include/config/uboot.release (if it exists) -- 2.13.5 ___ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot
[U-Boot] [PATCH v2 4/5] vsprintf.c: add GUID printing
This works (roughly) the same way as linux's, but we currently always print lower-case (ie. we just keep %pUB and %pUL for compat with linux), mostly just because that is what uuid_bin_to_str() supports. %pUb: 01020304-0506-0708-090a-0b0c0d0e0f10 %pUl: 04030201-0605-0807-090a-0b0c0d0e0f10 It will be used by a later efi_loader paths for efi variables and for device-path-to-text protocol, and also quite useful for debug prints of protocol GUIDs. Signed-off-by: Rob Clark Tested-by: Heinrich Schuchardt --- examples/api/Makefile | 1 + include/config_fallbacks.h | 1 + lib/vsprintf.c | 46 -- 3 files changed, 46 insertions(+), 2 deletions(-) diff --git a/examples/api/Makefile b/examples/api/Makefile index 87c15d0f68..899527267d 100644 --- a/examples/api/Makefile +++ b/examples/api/Makefile @@ -35,6 +35,7 @@ EXT_COBJ-y += lib/string.o EXT_COBJ-y += lib/time.o EXT_COBJ-y += lib/vsprintf.o EXT_COBJ-y += lib/charset.o +EXT_COBJ-$(CONFIG_LIB_UUID) += lib/uuid.o EXT_SOBJ-$(CONFIG_PPC) += arch/powerpc/lib/ppcstring.o ifeq ($(ARCH),arm) EXT_SOBJ-$(CONFIG_USE_ARCH_MEMSET) += arch/arm/lib/memset.o diff --git a/include/config_fallbacks.h b/include/config_fallbacks.h index 46b7a2a6f2..2c4d43d672 100644 --- a/include/config_fallbacks.h +++ b/include/config_fallbacks.h @@ -58,6 +58,7 @@ #if (CONFIG_IS_ENABLED(PARTITION_UUIDS) || \ CONFIG_IS_ENABLED(EFI_PARTITION) || \ + CONFIG_IS_ENABLED(EFI_LOADER) || \ defined(CONFIG_RANDOM_UUID) || \ defined(CONFIG_CMD_UUID) || \ defined(CONFIG_BOOTP_PXE)) && \ diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 97bed9d36d..dd572d2868 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -18,6 +18,7 @@ #include #include +#include #include #define noinline __attribute__((noinline)) @@ -366,6 +367,40 @@ static char *ip4_addr_string(char *buf, char *end, u8 *addr, int field_width, } #endif +#ifdef CONFIG_LIB_UUID +/* + * This works (roughly) the same way as linux's, but we currently always + * print lower-case (ie. we just keep %pUB and %pUL for compat with linux), + * mostly just because that is what uuid_bin_to_str() supports. + * + * %pUb: 01020304-0506-0708-090a-0b0c0d0e0f10 + * %pUl: 04030201-0605-0807-090a-0b0c0d0e0f10 + */ +static char *uuid_string(char *buf, char *end, u8 *addr, int field_width, +int precision, int flags, const char *fmt) +{ + char uuid[UUID_STR_LEN + 1]; + int str_format = UUID_STR_FORMAT_STD; + + switch (*(++fmt)) { + case 'L': + case 'l': + str_format = UUID_STR_FORMAT_GUID; + break; + case 'B': + case 'b': + /* this is the default */ + break; + default: + break; + } + + uuid_bin_to_str(addr, uuid, str_format); + + return string(buf, end, uuid, field_width, precision, flags); +} +#endif + /* * Show a '%p' thing. A kernel extension is that the '%p' is followed * by an extra set of alphanumeric characters that are extended format @@ -399,8 +434,8 @@ static char *pointer(const char *fmt, char *buf, char *end, void *ptr, flags); #endif -#ifdef CONFIG_CMD_NET switch (*fmt) { +#ifdef CONFIG_CMD_NET case 'a': flags |= SPECIAL | ZEROPAD; @@ -430,8 +465,15 @@ static char *pointer(const char *fmt, char *buf, char *end, void *ptr, precision, flags); flags &= ~SPECIAL; break; - } #endif +#ifdef CONFIG_LIB_UUID + case 'U': + return uuid_string(buf, end, ptr, field_width, precision, + flags, fmt); +#endif + default: + break; + } flags |= SMALL; if (field_width == -1) { field_width = 2*sizeof(void *); -- 2.13.5 ___ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot
[U-Boot] [PATCH v2 5/5] examples: add fallback memcpy
Solves build issue: Building current source for 134 boards (12 threads, 1 job per thread) arm: + lsxhl +examples/api/vsprintf.o: In function `string16': +lib/vsprintf.c:278: undefined reference to `memcpy' +examples/api/uuid.o: In function `uuid_bin_to_str': +lib/uuid.c:197: undefined reference to `memcpy' +lib/uuid.c:199: undefined reference to `memcpy' +make[3]: *** [examples/api/demo] Error 1 +make[2]: *** [examples/api] Error 2 +make[1]: *** [examples] Error 2 +make: *** [sub-make] Error 2 13301 /134sheevaplug Signed-off-by: Rob Clark --- examples/api/glue.c | 12 1 file changed, 12 insertions(+) diff --git a/examples/api/glue.c b/examples/api/glue.c index 8aabf32c89..575c1e55f3 100644 --- a/examples/api/glue.c +++ b/examples/api/glue.c @@ -416,3 +416,15 @@ void ub_display_clear(void) { syscall(API_DISPLAY_CLEAR, NULL); } + +__weak void *memcpy(void *dest, const void *src, size_t size) +{ + unsigned char *dptr = dest; + const unsigned char *ptr = src; + const unsigned char *end = src + size; + + while (ptr < end) + *dptr++ = *ptr++; + + return dest; +} -- 2.13.5 ___ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot
[U-Boot] [PATCH v2 3/5] vsprintf.c: add UTF-16 string (%ls) support
This is convenient for efi_loader which deals a lot with UTF-16. Only enabled with CC_SHORT_WCHAR, leaving room to add a UTF-32 version when CC_SHORT_WCHAR is not enabled. Signed-off-by: Rob Clark Reviewed-by: Simon Glass --- examples/api/Makefile | 1 + lib/vsprintf.c| 30 -- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/examples/api/Makefile b/examples/api/Makefile index dab6398bab..87c15d0f68 100644 --- a/examples/api/Makefile +++ b/examples/api/Makefile @@ -34,6 +34,7 @@ EXT_COBJ-y += lib/div64.o EXT_COBJ-y += lib/string.o EXT_COBJ-y += lib/time.o EXT_COBJ-y += lib/vsprintf.o +EXT_COBJ-y += lib/charset.o EXT_SOBJ-$(CONFIG_PPC) += arch/powerpc/lib/ppcstring.o ifeq ($(ARCH),arm) EXT_SOBJ-$(CONFIG_USE_ARCH_MEMSET) += arch/arm/lib/memset.o diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 874a2951f7..97bed9d36d 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -17,6 +17,7 @@ #include #include +#include #include #define noinline __attribute__((noinline)) @@ -270,6 +271,26 @@ static char *string(char *buf, char *end, char *s, int field_width, return buf; } +static char *string16(char *buf, char *end, u16 *s, int field_width, + int precision, int flags) +{ + u16 *str = s ? s : L""; + int utf16_len = utf16_strnlen(str, precision); + u8 utf8[utf16_len * MAX_UTF8_PER_UTF16]; + int utf8_len, i; + + utf8_len = utf16_to_utf8(utf8, str, utf16_len) - utf8; + + if (!(flags & LEFT)) + while (utf8_len < field_width--) + ADDCH(buf, ' '); + for (i = 0; i < utf8_len; ++i) + ADDCH(buf, utf8[i]); + while (utf8_len < field_width--) + ADDCH(buf, ' '); + return buf; +} + #ifdef CONFIG_CMD_NET static const char hex_asc[] = "0123456789abcdef"; #define hex_asc_lo(x) hex_asc[((x) & 0x0f)] @@ -528,8 +549,13 @@ repeat: continue; case 's': - str = string(str, end, va_arg(args, char *), -field_width, precision, flags); + if (qualifier == 'l' && !IS_ENABLED(CONFIG_SPL_BUILD)) { + str = string16(str, end, va_arg(args, u16 *), + field_width, precision, flags); + } else { + str = string(str, end, va_arg(args, char *), +field_width, precision, flags); + } continue; case 'p': -- 2.13.5 ___ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot
[U-Boot] [PATCH v2 2/5] lib: add some utf16 handling helpers
We'll eventually want these in a few places in efi_loader, and also vsprintf. Signed-off-by: Rob Clark --- include/charset.h| 65 lib/Makefile | 1 + lib/charset.c| 101 +++ lib/efi_loader/efi_console.c | 17 ++-- 4 files changed, 170 insertions(+), 14 deletions(-) create mode 100644 include/charset.h create mode 100644 lib/charset.c diff --git a/include/charset.h b/include/charset.h new file mode 100644 index 00..39279f746a --- /dev/null +++ b/include/charset.h @@ -0,0 +1,65 @@ +/* + * charset conversion utils + * + * Copyright (c) 2017 Rob Clark + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __CHARSET_H_ +#define __CHARSET_H_ + +#define MAX_UTF8_PER_UTF16 4 + +/** + * utf16_strlen() - Get the length of an utf16 string + * + * Returns the number of 16 bit characters in an utf16 string, not + * including the terminating NULL character. + * + * @in the string to measure + * @return the string length + */ +size_t utf16_strlen(const uint16_t *in); + +/** + * utf16_strnlen() - Get the length of a fixed-size utf16 string. + * + * Returns the number of 16 bit characters in an utf16 string, + * not including the terminating NULL character, but at most + * 'count' number of characters. In doing this, utf16_strnlen() + * looks at only the first 'count' characters. + * + * @in the string to measure + * @count the maximum number of characters to count + * @return the string length, up to a maximum of 'count' + */ +size_t utf16_strnlen(const uint16_t *in, size_t count); + +/** + * utf16_strcpy() - UTF16 equivalent of strcpy() + */ +uint16_t *utf16_strcpy(uint16_t *dest, const uint16_t *src); + +/** + * utf16_strdup() - UTF16 equivalent of strdup() + */ +uint16_t *utf16_strdup(const uint16_t *s); + +/** + * utf16_to_utf8() - Convert an utf16 string to utf8 + * + * Converts 'size' characters of the utf16 string 'src' to utf8 + * written to the 'dest' buffer. + * + * NOTE that a single utf16 character can generate up to 4 utf8 + * characters. See MAX_UTF8_PER_UTF16. + * + * @dest the destination buffer to write the utf8 characters + * @srcthe source utf16 string + * @size the number of utf16 characters to convert + * @return the pointer to the first unwritten byte in 'dest' + */ +uint8_t *utf16_to_utf8(uint8_t *dest, const uint16_t *src, size_t size); + +#endif /* __CHARSET_H_ */ diff --git a/lib/Makefile b/lib/Makefile index 2eef1eb80e..24df11b88f 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -19,6 +19,7 @@ obj-$(CONFIG_OF_LIVE) += of_live.o obj-$(CONFIG_CMD_DHRYSTONE) += dhry/ obj-$(CONFIG_AES) += aes.o +obj-y += charset.o obj-$(CONFIG_USB_TTY) += circbuf.o obj-y += crc7.o obj-y += crc8.o diff --git a/lib/charset.c b/lib/charset.c new file mode 100644 index 00..ff76e88c77 --- /dev/null +++ b/lib/charset.c @@ -0,0 +1,101 @@ +/* + * charset conversion utils + * + * Copyright (c) 2017 Rob Clark + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include + +/* + * utf8/utf16 conversion mostly lifted from grub + */ + +size_t utf16_strlen(const uint16_t *in) +{ + size_t i; + for (i = 0; in[i]; i++); + return i; +} + +size_t utf16_strnlen(const uint16_t *in, size_t count) +{ + size_t i; + for (i = 0; count-- && in[i]; i++); + return i; +} + +uint16_t *utf16_strcpy(uint16_t *dest, const uint16_t *src) +{ + uint16_t *tmp = dest; + + while ((*dest++ = *src++) != '\0') + /* nothing */; + return tmp; + +} + +uint16_t *utf16_strdup(const uint16_t *s) +{ + uint16_t *new; + if (!s || !(new = malloc((utf16_strlen(s) + 1) * 2))) + return NULL; + utf16_strcpy(new, s); + return new; +} + +/* Convert UTF-16 to UTF-8. */ +uint8_t *utf16_to_utf8(uint8_t *dest, const uint16_t *src, size_t size) +{ + uint32_t code_high = 0; + + while (size--) { + uint32_t code = *src++; + + if (code_high) { + if (code >= 0xDC00 && code <= 0xDFFF) { + /* Surrogate pair. */ + code = ((code_high - 0xD800) << 10) + (code - 0xDC00) + 0x1; + + *dest++ = (code >> 18) | 0xF0; + *dest++ = ((code >> 12) & 0x3F) | 0x80; + *dest++ = ((code >> 6) & 0x3F) | 0x80; + *dest++ = (code & 0x3F) | 0x80; + } else { + /* Error... */ + *dest++ = '?'; + /* *src may be valid. Don't eat it. */ + src--; + } + + code_high = 0; + } else { + if (code <= 0x007F) { + *dest++ = cod
Re: [U-Boot] [PATCH 05/13] usb: gadget: Make g_dnl USB settings common
Hi Maxime, The g_dnl USB settings for the vendor ID, product ID and manufacturer are actually common settings that can and should be shared by all the gadgets. Make them common by renaming them, and convert all the users. Reviewed-by: Lukasz Majewski Signed-off-by: Maxime Ripard --- board/samsung/common/gadget.c| 4 ++-- board/siemens/common/factoryset.c| 4 ++-- configs/A13-OLinuXino_defconfig | 6 +++--- configs/A20-OLinuXino-Lime2-eMMC_defconfig | 6 +++--- configs/A20-OLinuXino-Lime2_defconfig| 6 +++--- configs/CHIP_defconfig | 6 +++--- configs/CHIP_pro_defconfig | 6 +++--- configs/Cubietruck_defconfig | 6 +++--- configs/Nintendo_NES_Classic_Edition_defconfig | 6 +++--- configs/Sinlinx_SinA33_defconfig | 6 +++--- configs/am335x_baltos_defconfig | 6 +++--- configs/am335x_boneblack_defconfig | 6 +++--- configs/am335x_boneblack_vboot_defconfig | 6 +++--- configs/am335x_evm_defconfig | 6 +++--- configs/am335x_evm_nor_defconfig | 6 +++--- configs/am335x_evm_norboot_defconfig | 6 +++--- configs/am335x_evm_spiboot_defconfig | 6 +++--- configs/am335x_evm_usbspl_defconfig | 6 +++--- configs/am335x_hs_evm_defconfig | 6 +++--- configs/am43xx_evm_defconfig | 6 +++--- configs/am43xx_evm_ethboot_defconfig | 6 +++--- configs/am43xx_evm_qspiboot_defconfig| 6 +++--- configs/am43xx_evm_usbhost_boot_defconfig| 6 +++--- configs/am43xx_hs_evm_defconfig | 6 +++--- configs/am57xx_evm_defconfig | 6 +++--- configs/am57xx_evm_nodt_defconfig| 6 +++--- configs/am57xx_hs_evm_defconfig | 6 +++--- configs/apalis-tk1_defconfig | 6 +++--- configs/apalis_imx6_defconfig| 6 +++--- configs/apalis_imx6_nospl_com_defconfig | 6 +++--- configs/apalis_imx6_nospl_it_defconfig | 6 +++--- configs/apalis_t30_defconfig | 6 +++--- configs/bcm11130_defconfig | 6 +++--- configs/bcm11130_nand_defconfig | 6 +++--- configs/bcm23550_w1d_defconfig | 6 +++--- configs/bcm28155_ap_defconfig| 6 +++--- configs/bcm28155_w1d_defconfig | 6 +++--- configs/beaver_defconfig | 6 +++--- configs/birdland_bav335a_defconfig | 6 +++--- configs/birdland_bav335b_defconfig | 6 +++--- configs/cei-tk1-som_defconfig| 6 +++--- configs/cgtqmx6eval_defconfig| 6 +++--- configs/chromebit_mickey_defconfig | 6 +++--- configs/chromebook_jerry_defconfig | 6 +++--- configs/chromebook_minnie_defconfig | 6 +++--- configs/colibri_imx6_defconfig | 6 +++--- configs/colibri_imx6_nospl_defconfig | 6 +++--- configs/colibri_imx7_defconfig | 6 +++--- configs/colibri_t20_defconfig| 6 +++--- configs/colibri_t30_defconfig| 6 +++--- configs/colibri_vf_defconfig | 6 +++--- configs/corvus_defconfig | 6 +++--- configs/dalmore_defconfig| 6 +++--- configs/dms-ba16-1g_defconfig| 6 +++--- configs/dms-ba16_defconfig | 6 +++--- configs/dra7xx_evm_defconfig | 6 +++--- configs/dra7xx_hs_evm_defconfig | 6 +++--- configs/draco_defconfig | 6 +++--- configs/e2220-1170_defconfig | 6 +++--- configs/edison_defconfig | 6 +++--- configs/etamin_defconfig | 6 +++--- configs/evb-rk3036_defconfig | 6 +++--- configs/evb-rk3229_defconfig | 6 +++--- configs/evb-rk3288_defconfig | 6 +++--- configs/evb-rk3328_defconfig | 6 +++--- configs/fennec-rk3288_defconfig | 6 +++--- configs/firefly-rk3288_defconfig | 6 +++--- configs/gwventana_emmc_defconfig | 6 +++--- configs/gwventana_gw5904_defconfig | 6 +++--- configs/gwventana_nand_defconfig | 6 +++--- configs/jetson-tk1_defconfig | 6 +++--- configs/kc1_defconfig| 6 +++--- configs/kylin-rk3036_defconfig | 6 +++--- configs/ma5d4evk_defconfig | 6 +++--- configs/miqi-rk3288_defconfig
[U-Boot] VU#166743: Das U-Boot AES-CBC encryption
I apologize if I missed it, but I haven't see any mention of this recent vulnerability here, excerpts below. http://www.kb.cert.org/vuls/id/166743 -snip- Vulnerability Note VU#166743 Das U-Boot AES-CBC encryption implementation contains multiple vulnerabilities Original Release date: 08 Sep 2017 Das U-Boot is a device bootloader that can read its configuration from an AES encrypted file. For devices utilizing this environment encryption mode, U-Boot's use of a zero initialization vector and improper handling of an error condition may allow attacks against the underlying cryptographic implementation and allow an attacker to decrypt the data. An attacker with physical access to the device may be able to decrypt the device's contents. The CERT/CC is currently unaware of a practical solution to this problem. -snip- ___ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot
[U-Boot] [PATCH v3 0/9] fs/fat: cleanups + readdir implementation
Introduce directory traversal iterators, and implement fs_readdir() which is needed by EFI_LOADER. The part re-working fat.c to use the directory iterators itself is nearly a 2:1 negative diffstat, and a pretty big cleanup. I fixed one or two other small issues along the way. v2: fix a couple issues (partition is whole disk, and traversing ".." up to root directory) v3: mostly addition of comments plus cleaning up open-coded sector <-> cluster conversions, and some FAT32 fixes for large directories Rob Clark (9): fs/fat: split out helper to init fsdata fs/fat: introduce new director iterators fat/fs: convert to directory iterators fs: add fs_readdir() fs/fat: implement opendir/readdir/closedir fat/fs: remove a bunch of dead code fat/fs: move ls to generic implementation fs/fat: fix case for FAT shortnames fs/fat: Clean up open-coded sector <-> cluster conversions disk/part.c| 31 +- fs/fat/Makefile|4 - fs/fat/fat.c | 1062 ++-- fs/fat/fat_write.c | 12 +- fs/fat/file.c | 183 - fs/fs.c| 137 ++- include/fat.h | 49 ++- include/fs.h | 67 include/part.h |9 + 9 files changed, 700 insertions(+), 854 deletions(-) delete mode 100644 fs/fat/file.c -- 2.13.5 ___ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot
[U-Boot] [PATCH v3 1/9] fs/fat: split out helper to init fsdata
Want to re-use this in fat dirent iterator in next patch. Signed-off-by: Rob Clark Reviewed-by: Łukasz Majewski Reviewed-by: Simon Glass --- fs/fat/fat.c | 73 +++ include/fat.h | 1 + 2 files changed, 44 insertions(+), 30 deletions(-) diff --git a/fs/fat/fat.c b/fs/fat/fat.c index 465a6875ed..e1c0a15dc7 100644 --- a/fs/fat/fat.c +++ b/fs/fat/fat.c @@ -808,35 +808,17 @@ exit: return ret; } -__u8 do_fat_read_at_block[MAX_CLUSTSIZE] - __aligned(ARCH_DMA_MINALIGN); - -int do_fat_read_at(const char *filename, loff_t pos, void *buffer, - loff_t maxsize, int dols, int dogetsize, loff_t *size) +static int get_fs_info(fsdata *mydata) { - char fnamecopy[2048]; boot_sector bs; volume_info volinfo; - fsdata datablock; - fsdata *mydata = &datablock; - dir_entry *dentptr = NULL; - __u16 prevcksum = 0x; - char *subname = ""; - __u32 cursect; - int idx, isdir = 0; - int files = 0, dirs = 0; - int ret = -1; - int firsttime; __u32 root_cluster = 0; - __u32 read_blk; - int rootdir_size = 0; - int buffer_blk_cnt; - int do_read; - __u8 *dir_ptr; + int ret; - if (read_bootsectandvi(&bs, &volinfo, &mydata->fatsize)) { + ret = read_bootsectandvi(&bs, &volinfo, &mydata->fatsize); + if (ret) { debug("Error: reading boot sector\n"); - return -1; + return ret; } if (mydata->fatsize == 32) { @@ -848,8 +830,7 @@ int do_fat_read_at(const char *filename, loff_t pos, void *buffer, mydata->fat_sect = bs.reserved; - cursect = mydata->rootdir_sect - = mydata->fat_sect + mydata->fatlength * bs.fats; + mydata->rootdir_sect = mydata->fat_sect + mydata->fatlength * bs.fats; mydata->sect_size = (bs.sector_size[1] << 8) + bs.sector_size[0]; mydata->clust_size = bs.cluster_size; @@ -863,12 +844,12 @@ int do_fat_read_at(const char *filename, loff_t pos, void *buffer, mydata->data_begin = mydata->rootdir_sect - (mydata->clust_size * 2); } else { - rootdir_size = ((bs.dir_entries[1] * (int)256 + -bs.dir_entries[0]) * -sizeof(dir_entry)) / -mydata->sect_size; + mydata->rootdir_size = ((bs.dir_entries[1] * (int)256 + +bs.dir_entries[0]) * +sizeof(dir_entry)) / +mydata->sect_size; mydata->data_begin = mydata->rootdir_sect + - rootdir_size - + mydata->rootdir_size - (mydata->clust_size * 2); } @@ -893,6 +874,38 @@ int do_fat_read_at(const char *filename, loff_t pos, void *buffer, debug("Sector size: %d, cluster size: %d\n", mydata->sect_size, mydata->clust_size); + return 0; +} + +__u8 do_fat_read_at_block[MAX_CLUSTSIZE] + __aligned(ARCH_DMA_MINALIGN); + +int do_fat_read_at(const char *filename, loff_t pos, void *buffer, + loff_t maxsize, int dols, int dogetsize, loff_t *size) +{ + char fnamecopy[2048]; + fsdata datablock; + fsdata *mydata = &datablock; + dir_entry *dentptr = NULL; + __u16 prevcksum = 0x; + char *subname = ""; + __u32 cursect; + int idx, isdir = 0; + int files = 0, dirs = 0; + int ret = -1; + int firsttime; + __u32 root_cluster = 0; + __u32 read_blk; + int rootdir_size = 0; + int buffer_blk_cnt; + int do_read; + __u8 *dir_ptr; + + if (get_fs_info(mydata)) + return -1; + + cursect = mydata->rootdir_sect; + /* "cwd" is always the root... */ while (ISDIRDELIM(*filename)) filename++; diff --git a/include/fat.h b/include/fat.h index 71879f01ca..b671ee8f81 100644 --- a/include/fat.h +++ b/include/fat.h @@ -174,6 +174,7 @@ typedef struct { __u16 clust_size; /* Size of clusters in sectors */ int data_begin; /* The sector of the first cluster, can be negative */ int fatbufnum; /* Used by get_fatent, init to -1 */ + int rootdir_size; /* Size of root dir for non-FAT32 */ } fsdata; typedef int(file_detectfs_func)(void); -- 2.13.5 ___ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot
[U-Boot] [PATCH v3 5/9] fs/fat: implement opendir/readdir/closedir
Implement the readdir interface using the directory iterators. Signed-off-by: Rob Clark Reviewed-by: Łukasz Majewski --- fs/fat/fat.c | 61 1 file changed, 61 insertions(+) diff --git a/fs/fat/fat.c b/fs/fat/fat.c index bbba7947ee..82ddb7eab1 100644 --- a/fs/fat/fat.c +++ b/fs/fat/fat.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -1146,6 +1147,66 @@ int fat_read_file(const char *filename, void *buf, loff_t offset, loff_t len, return ret; } +typedef struct { + struct fs_dir_stream parent; + struct fs_dirent dirent; + fsdata fsdata; + fat_itr itr; +} fat_dir; + +int fat_opendir(const char *filename, struct fs_dir_stream **dirsp) +{ + fat_dir *dir = malloc(sizeof(*dir)); + int ret; + + if (!dir) + return -ENOMEM; + + ret = fat_itr_root(&dir->itr, &dir->fsdata); + if (ret) + goto fail; + + ret = fat_itr_resolve(&dir->itr, filename, TYPE_DIR); + if (ret) + goto fail; + + *dirsp = (struct fs_dir_stream *)dir; + return 0; + +fail: + free(dir); + return ret; +} + +int fat_readdir(struct fs_dir_stream *dirs, struct fs_dirent **dentp) +{ + fat_dir *dir = (fat_dir *)dirs; + struct fs_dirent *dent = &dir->dirent; + + if (!fat_itr_next(&dir->itr)) + return -ENOENT; + + memset(dent, 0, sizeof(*dent)); + strcpy(dent->name, dir->itr.name); + + if (fat_itr_isdir(&dir->itr)) { + dent->type = FS_DT_DIR; + } else { + dent->type = FS_DT_REG; + dent->size = FAT2CPU32(dir->itr.dent->size); + } + + *dentp = dent; + + return 0; +} + +void fat_closedir(struct fs_dir_stream *dirs) +{ + fat_dir *dir = (fat_dir *)dirs; + free(dir); +} + void fat_close(void) { } -- 2.13.5 ___ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot
[U-Boot] [PATCH v3 4/9] fs: add fs_readdir()
Needed to support efi file protocol. The fallback.efi loader wants to be able to read the contents of the /EFI directory to find an OS to boot. Modelled after POSIX opendir()/readdir()/closedir(). Unlike the other fs APIs, this is stateful (ie. state is held in the FS_DIR "directory stream"), to avoid re-traversing of the directory structure at each step. The directory stream must be released with closedir() when it is no longer needed. Signed-off-by: Rob Clark Reviewed-by: Łukasz Majewski --- disk/part.c| 31 ++--- fs/fs.c| 104 + include/fs.h | 67 + include/part.h | 9 + 4 files changed, 199 insertions(+), 12 deletions(-) diff --git a/disk/part.c b/disk/part.c index c67fdacc79..aa9183d696 100644 --- a/disk/part.c +++ b/disk/part.c @@ -331,6 +331,24 @@ int part_get_info(struct blk_desc *dev_desc, int part, return -1; } +int part_get_info_whole_disk(struct blk_desc *dev_desc, disk_partition_t *info) +{ + info->start = 0; + info->size = dev_desc->lba; + info->blksz = dev_desc->blksz; + info->bootable = 0; + strcpy((char *)info->type, BOOT_PART_TYPE); + strcpy((char *)info->name, "Whole Disk"); +#if CONFIG_IS_ENABLED(PARTITION_UUIDS) + info->uuid[0] = 0; +#endif +#ifdef CONFIG_PARTITION_TYPE_GUID + info->type_guid[0] = 0; +#endif + + return 0; +} + int blk_get_device_by_str(const char *ifname, const char *dev_hwpart_str, struct blk_desc **dev_desc) { @@ -523,18 +541,7 @@ int blk_get_device_part_str(const char *ifname, const char *dev_part_str, (*dev_desc)->log2blksz = LOG2((*dev_desc)->blksz); - info->start = 0; - info->size = (*dev_desc)->lba; - info->blksz = (*dev_desc)->blksz; - info->bootable = 0; - strcpy((char *)info->type, BOOT_PART_TYPE); - strcpy((char *)info->name, "Whole Disk"); -#if CONFIG_IS_ENABLED(PARTITION_UUIDS) - info->uuid[0] = 0; -#endif -#ifdef CONFIG_PARTITION_TYPE_GUID - info->type_guid[0] = 0; -#endif + part_get_info_whole_disk(*dev_desc, info); ret = 0; goto cleanup; diff --git a/fs/fs.c b/fs/fs.c index 13cd3626c6..fc0c953fcb 100644 --- a/fs/fs.c +++ b/fs/fs.c @@ -21,6 +21,7 @@ DECLARE_GLOBAL_DATA_PTR; static struct blk_desc *fs_dev_desc; +static int fs_dev_part; static disk_partition_t fs_partition; static int fs_type = FS_TYPE_ANY; @@ -69,6 +70,12 @@ static inline int fs_uuid_unsupported(char *uuid_str) return -1; } +static inline int fs_opendir_unsupported(const char *filename, +struct fs_dir_stream **dirs) +{ + return -EACCES; +} + struct fstype_info { int fstype; char *name; @@ -92,6 +99,20 @@ struct fstype_info { loff_t len, loff_t *actwrite); void (*close)(void); int (*uuid)(char *uuid_str); + /* +* Open a directory stream. On success return 0 and directory +* stream pointer via 'dirsp'. On error, return -errno. See +* fs_opendir(). +*/ + int (*opendir)(const char *filename, struct fs_dir_stream **dirsp); + /* +* Read next entry from directory stream. On success return 0 +* and directory entry pointer via 'dentp'. On error return +* -errno. See fs_readdir(). +*/ + int (*readdir)(struct fs_dir_stream *dirs, struct fs_dirent **dentp); + /* see fs_closedir() */ + void (*closedir)(struct fs_dir_stream *dirs); }; static struct fstype_info fstypes[] = { @@ -112,6 +133,7 @@ static struct fstype_info fstypes[] = { .write = fs_write_unsupported, #endif .uuid = fs_uuid_unsupported, + .opendir = fs_opendir_unsupported, }, #endif #ifdef CONFIG_FS_EXT4 @@ -131,6 +153,7 @@ static struct fstype_info fstypes[] = { .write = fs_write_unsupported, #endif .uuid = ext4fs_uuid, + .opendir = fs_opendir_unsupported, }, #endif #ifdef CONFIG_SANDBOX @@ -146,6 +169,7 @@ static struct fstype_info fstypes[] = { .read = fs_read_sandbox, .write = fs_write_sandbox, .uuid = fs_uuid_unsupported, + .opendir = fs_opendir_unsupported, }, #endif #ifdef CONFIG_CMD_UBIFS @@ -161,6 +185,7 @@ static struct fstype_info fstypes[] = { .read = ubifs_read, .write = fs_write_unsupported, .uuid = fs_uuid_unsupported, + .opendir = fs_opendir_unsupported, }, #endif { @@ -175,6 +200,7 @@ static struct fstype_info fstypes[] = { .read = fs_read_unsupported, .write = fs_write_unsupported, .uuid =
[U-Boot] [PATCH v3 8/9] fs/fat: fix case for FAT shortnames
Noticed when comparing our output to linux. There are some lcase bits which control whether filename and/or extension should be downcase'd. Signed-off-by: Rob Clark Reviewed-by: Łukasz Majewski --- fs/fat/fat.c | 16 ++-- fs/fat/fat_write.c | 4 ++-- include/fat.h | 6 +- 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/fs/fat/fat.c b/fs/fat/fat.c index c951d84f57..65873a2c2a 100644 --- a/fs/fat/fat.c +++ b/fs/fat/fat.c @@ -29,11 +29,13 @@ static const int vfat_enabled = 0; #endif /* - * Convert a string to lowercase. + * Convert a string to lowercase. Converts at most 'len' characters, + * 'len' may be larger than the length of 'str' if 'str' is NULL + * terminated. */ -static void downcase(char *str) +static void downcase(char *str, size_t len) { - while (*str != '\0') { + while (*str != '\0' && len--) { *str = tolower(*str); str++; } @@ -131,10 +133,13 @@ static void get_name(dir_entry *dirent, char *s_name) ptr = s_name; while (*ptr && *ptr != ' ') ptr++; + if (dirent->lcase & CASE_LOWER_BASE) + downcase(s_name, (unsigned)(ptr - s_name)); if (dirent->ext[0] && dirent->ext[0] != ' ') { - *ptr = '.'; - ptr++; + *ptr++ = '.'; memcpy(ptr, dirent->ext, 3); + if (dirent->lcase & CASE_LOWER_EXT) + downcase(ptr, 3); ptr[3] = '\0'; while (*ptr && *ptr != ' ') ptr++; @@ -144,7 +149,6 @@ static void get_name(dir_entry *dirent, char *s_name) *s_name = '\0'; else if (*s_name == aRING) *s_name = DELETED_FLAG; - downcase(s_name); } static int flush_dirty_fat_buffer(fsdata *mydata); diff --git a/fs/fat/fat_write.c b/fs/fat/fat_write.c index 4ca024c208..d0468baf8f 100644 --- a/fs/fat/fat_write.c +++ b/fs/fat/fat_write.c @@ -345,7 +345,7 @@ get_long_file_name(fsdata *mydata, int curclust, __u8 *cluster, *l_name = '\0'; else if (*l_name == aRING) *l_name = DELETED_FLAG; - downcase(l_name); + downcase(l_name, INT_MAX); /* Return the real directory entry */ *retdent = realdent; @@ -981,7 +981,7 @@ static int do_fat_write(const char *filename, void *buffer, loff_t size, memcpy(l_filename, filename, name_len); l_filename[name_len] = 0; /* terminate the string */ - downcase(l_filename); + downcase(l_filename, INT_MAX); startsect = mydata->rootdir_sect; retdent = find_directory_entry(mydata, startsect, diff --git a/include/fat.h b/include/fat.h index 83cd90017e..0f58939124 100644 --- a/include/fat.h +++ b/include/fat.h @@ -128,10 +128,14 @@ typedef struct volume_info /* Boot sign comes last, 2 bytes */ } volume_info; +/* see dir_entry::lcase: */ +#define CASE_LOWER_BASE8 /* base (name) is lower case */ +#define CASE_LOWER_EXT 16 /* extension is lower case */ + typedef struct dir_entry { charname[8],ext[3]; /* Name and extension */ __u8attr; /* Attribute bits */ - __u8lcase; /* Case for base and extension */ + __u8lcase; /* Case for name and ext (CASE_LOWER_x) */ __u8ctime_ms; /* Creation time, milliseconds */ __u16 ctime; /* Creation time */ __u16 cdate; /* Creation date */ -- 2.13.5 ___ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot
[U-Boot] [PATCH v3 3/9] fat/fs: convert to directory iterators
And drop a whole lot of ugly code! Signed-off-by: Rob Clark Reviewed-by: Łukasz Majewski --- fs/fat/fat.c | 722 +++--- include/fat.h | 6 - 2 files changed, 76 insertions(+), 652 deletions(-) diff --git a/fs/fat/fat.c b/fs/fat/fat.c index ee2bbe38f1..bbba7947ee 100644 --- a/fs/fat/fat.c +++ b/fs/fat/fat.c @@ -119,22 +119,6 @@ int fat_register_device(struct blk_desc *dev_desc, int part_no) } /* - * Get the first occurence of a directory delimiter ('/' or '\') in a string. - * Return index into string if found, -1 otherwise. - */ -static int dirdelim(char *str) -{ - char *start = str; - - while (*str != '\0') { - if (ISDIRDELIM(*str)) - return str - start; - str++; - } - return -1; -} - -/* * Extract zero terminated short name from a directory entry. */ static void get_name(dir_entry *dirent, char *s_name) @@ -468,95 +452,6 @@ static int slot2str(dir_slot *slotptr, char *l_name, int *idx) return 0; } -/* - * Extract the full long filename starting at 'retdent' (which is really - * a slot) into 'l_name'. If successful also copy the real directory entry - * into 'retdent' - * Return 0 on success, -1 otherwise. - */ -static int -get_vfatname(fsdata *mydata, int curclust, __u8 *cluster, -dir_entry *retdent, char *l_name) -{ - dir_entry *realdent; - dir_slot *slotptr = (dir_slot *)retdent; - __u8 *buflimit = cluster + mydata->sect_size * ((curclust == 0) ? - PREFETCH_BLOCKS : - mydata->clust_size); - __u8 counter = (slotptr->id & ~LAST_LONG_ENTRY_MASK) & 0xff; - int idx = 0; - - if (counter > VFAT_MAXSEQ) { - debug("Error: VFAT name is too long\n"); - return -1; - } - - while ((__u8 *)slotptr < buflimit) { - if (counter == 0) - break; - if (((slotptr->id & ~LAST_LONG_ENTRY_MASK) & 0xff) != counter) - return -1; - slotptr++; - counter--; - } - - if ((__u8 *)slotptr >= buflimit) { - dir_slot *slotptr2; - - if (curclust == 0) - return -1; - curclust = get_fatent(mydata, curclust); - if (CHECK_CLUST(curclust, mydata->fatsize)) { - debug("curclust: 0x%x\n", curclust); - printf("Invalid FAT entry\n"); - return -1; - } - - if (get_cluster(mydata, curclust, get_contents_vfatname_block, - mydata->clust_size * mydata->sect_size) != 0) { - debug("Error: reading directory block\n"); - return -1; - } - - slotptr2 = (dir_slot *)get_contents_vfatname_block; - while (counter > 0) { - if (((slotptr2->id & ~LAST_LONG_ENTRY_MASK) - & 0xff) != counter) - return -1; - slotptr2++; - counter--; - } - - /* Save the real directory entry */ - realdent = (dir_entry *)slotptr2; - while ((__u8 *)slotptr2 > get_contents_vfatname_block) { - slotptr2--; - slot2str(slotptr2, l_name, &idx); - } - } else { - /* Save the real directory entry */ - realdent = (dir_entry *)slotptr; - } - - do { - slotptr--; - if (slot2str(slotptr, l_name, &idx)) - break; - } while (!(slotptr->id & LAST_LONG_ENTRY_MASK)); - - l_name[idx] = '\0'; - if (*l_name == DELETED_FLAG) - *l_name = '\0'; - else if (*l_name == aRING) - *l_name = DELETED_FLAG; - downcase(l_name); - - /* Return the real directory entry */ - memcpy(retdent, realdent, sizeof(dir_entry)); - - return 0; -} - /* Calculate short name checksum */ static __u8 mkcksum(const char name[8], const char ext[3]) { @@ -573,169 +468,13 @@ static __u8 mkcksum(const char name[8], const char ext[3]) } /* - * Get the directory entry associated with 'filename' from the directory - * starting at 'startsect' + * TODO these should go away once fat_write is reworked to use the + * directory iterator */ __u8 get_dentfromdir_block[MAX_CLUSTSIZE] __aligned(ARCH_DMA_MINALIGN); - -static dir_entry *get_dentfromdir(fsdata *mydata, int startsect, - char *filename, dir_entry *retdent, - int dols) -{ - __u16 prevcksum = 0x; - __u32 curclust = START(retdent); - int files = 0, dirs = 0; - -
[U-Boot] [PATCH v3 6/9] fat/fs: remove a bunch of dead code
Spotted by chance, when trying to remove file_fat_ls(), I noticed there were some dead users of the API. Signed-off-by: Rob Clark Acked-by: Stefan Brüns Reviewed-by: Simon Glass --- fs/fat/Makefile | 4 -- fs/fat/file.c | 183 include/fat.h | 20 --- 3 files changed, 207 deletions(-) delete mode 100644 fs/fat/file.c diff --git a/fs/fat/Makefile b/fs/fat/Makefile index b60e8486c4..3e2a6b01a8 100644 --- a/fs/fat/Makefile +++ b/fs/fat/Makefile @@ -5,7 +5,3 @@ obj-$(CONFIG_FS_FAT) := fat.o obj-$(CONFIG_FAT_WRITE):= fat_write.o - -ifndef CONFIG_SPL_BUILD -obj-$(CONFIG_FS_FAT) += file.o -endif diff --git a/fs/fat/file.c b/fs/fat/file.c deleted file mode 100644 index 89706117b9..00 --- a/fs/fat/file.c +++ /dev/null @@ -1,183 +0,0 @@ -/* - * file.c - * - * Mini "VFS" by Marcus Sundberg - * - * 2002-07-28 - rjo...@nexus-tech.net - ported to ppcboot v1.1.6 - * 2003-03-10 - khar...@nexus-tech.net - ported to uboot - * - * SPDX-License-Identifier:GPL-2.0+ - */ - -#include -#include -#include -#include -#include -#include - -/* Supported filesystems */ -static const struct filesystem filesystems[] = { - { file_fat_detectfs, file_fat_ls, file_fat_read, "FAT" }, -}; -#define NUM_FILESYS(sizeof(filesystems)/sizeof(struct filesystem)) - -/* The filesystem which was last detected */ -static int current_filesystem = FSTYPE_NONE; - -/* The current working directory */ -#define CWD_LEN511 -char file_cwd[CWD_LEN+1] = "/"; - -const char * -file_getfsname(int idx) -{ - if (idx < 0 || idx >= NUM_FILESYS) - return NULL; - - return filesystems[idx].name; -} - -static void -pathcpy(char *dest, const char *src) -{ - char *origdest = dest; - - do { - if (dest-file_cwd >= CWD_LEN) { - *dest = '\0'; - return; - } - *(dest) = *(src); - if (*src == '\0') { - if (dest-- != origdest && ISDIRDELIM(*dest)) { - *dest = '\0'; - } - return; - } - ++dest; - - if (ISDIRDELIM(*src)) - while (ISDIRDELIM(*src)) src++; - else - src++; - } while (1); -} - -int -file_cd(const char *path) -{ - if (ISDIRDELIM(*path)) { - while (ISDIRDELIM(*path)) path++; - strncpy(file_cwd+1, path, CWD_LEN-1); - } else { - const char *origpath = path; - char *tmpstr = file_cwd; - int back = 0; - - while (*tmpstr != '\0') tmpstr++; - do { - tmpstr--; - } while (ISDIRDELIM(*tmpstr)); - - while (*path == '.') { - path++; - while (*path == '.') { - path++; - back++; - } - if (*path != '\0' && !ISDIRDELIM(*path)) { - path = origpath; - back = 0; - break; - } - while (ISDIRDELIM(*path)) path++; - origpath = path; - } - - while (back--) { - /* Strip off path component */ - while (!ISDIRDELIM(*tmpstr)) { - tmpstr--; - } - if (tmpstr == file_cwd) { - /* Incremented again right after the loop. */ - tmpstr--; - break; - } - /* Skip delimiters */ - while (ISDIRDELIM(*tmpstr)) tmpstr--; - } - tmpstr++; - if (*path == '\0') { - if (tmpstr == file_cwd) { - *tmpstr = '/'; - tmpstr++; - } - *tmpstr = '\0'; - return 0; - } - *tmpstr = '/'; - pathcpy(tmpstr+1, path); - } - - return 0; -} - -int -file_detectfs(void) -{ - int i; - - current_filesystem = FSTYPE_NONE; - - for (i = 0; i < NUM_FILESYS; i++) { - if (filesystems[i].detect() == 0) { - strcpy(file_cwd, "/"); - current_filesystem = i; - break; - } - } - - return current_filesystem; -} - -int -file_ls(const char *dir) -{ - char fullpath[1024]; - const char *arg; - - if (current_filesystem == FSTYPE_NONE) { - printf("Can't list files
[U-Boot] [PATCH v3 9/9] fs/fat: Clean up open-coded sector <-> cluster conversions
Use the clust_to_sect() helper that was introduced earlier, and add an inverse sect_to_clust(), plus update the various spots that open-coded this conversion previously. Signed-off-by: Rob Clark --- fs/fat/fat.c | 8 +++- fs/fat/fat_write.c | 8 +++- include/fat.h | 6 +- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/fs/fat/fat.c b/fs/fat/fat.c index 65873a2c2a..f5f74c12ff 100644 --- a/fs/fat/fat.c +++ b/fs/fat/fat.c @@ -257,8 +257,7 @@ get_cluster(fsdata *mydata, __u32 clustnum, __u8 *buffer, unsigned long size) int ret; if (clustnum > 0) { - startsect = mydata->data_begin + - clustnum * mydata->clust_size; + startsect = clust_to_sect(mydata, clustnum); } else { startsect = mydata->rootdir_sect; } @@ -594,9 +593,8 @@ static int get_fs_info(fsdata *mydata) mydata->data_begin = mydata->rootdir_sect + mydata->rootdir_size - (mydata->clust_size * 2); - mydata->root_cluster = (mydata->rootdir_sect - - mydata->data_begin) / - mydata->clust_size; + mydata->root_cluster = + sect_to_clust(mydata, mydata->rootdir_sect); } mydata->fatbufnum = -1; diff --git a/fs/fat/fat_write.c b/fs/fat/fat_write.c index d0468baf8f..9d2e0ed74c 100644 --- a/fs/fat/fat_write.c +++ b/fs/fat/fat_write.c @@ -502,8 +502,7 @@ set_cluster(fsdata *mydata, __u32 clustnum, __u8 *buffer, int ret; if (clustnum > 0) - startsect = mydata->data_begin + - clustnum * mydata->clust_size; + startsect = clust_to_sect(mydata, clustnum); else startsect = mydata->rootdir_sect; @@ -751,8 +750,7 @@ static int check_overflow(fsdata *mydata, __u32 clustnum, loff_t size) __u32 startsect, sect_num, offset; if (clustnum > 0) { - startsect = mydata->data_begin + - clustnum * mydata->clust_size; + startsect = clust_to_sect(mydata, clustnum); } else { startsect = mydata->rootdir_sect; } @@ -791,7 +789,7 @@ static dir_entry *empty_dentptr; static dir_entry *find_directory_entry(fsdata *mydata, int startsect, char *filename, dir_entry *retdent, __u32 start) { - __u32 curclust = (startsect - mydata->data_begin) / mydata->clust_size; + __u32 curclust = sect_to_clust(mydata, startsect); debug("get_dentfromdir: %s\n", filename); diff --git a/include/fat.h b/include/fat.h index 0f58939124..bdeda95e6d 100644 --- a/include/fat.h +++ b/include/fat.h @@ -177,12 +177,16 @@ typedef struct { __u32 root_cluster; /* First cluster of root dir for FAT32 */ } fsdata; -/* TODO clean up places that are open-coding this: */ static inline u32 clust_to_sect(fsdata *fsdata, u32 clust) { return fsdata->data_begin + clust * fsdata->clust_size; } +static inline u32 sect_to_clust(fsdata *fsdata, u32 sect) +{ + return (sect - fsdata->data_begin) / fsdata->clust_size; +} + int file_fat_detectfs(void); int fat_exists(const char *filename); int fat_size(const char *filename, loff_t *size); -- 2.13.5 ___ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot
[U-Boot] [PATCH v3 7/9] fat/fs: move ls to generic implementation
Add a generic implementation of 'ls' using opendir/readdir/closedir, and replace fat's custom implementation. Other filesystems should move to the generic implementation after they add opendir/readdir/closedir support. Signed-off-by: Rob Clark Reviewed-by: Łukasz Majewski Reviewed-by: Simon Glass --- fs/fat/fat.c | 32 fs/fs.c | 35 +-- include/fat.h | 5 - 3 files changed, 37 insertions(+), 35 deletions(-) diff --git a/fs/fat/fat.c b/fs/fat/fat.c index 82ddb7eab1..c951d84f57 100644 --- a/fs/fat/fat.c +++ b/fs/fat/fat.c @@ -1029,38 +1029,6 @@ int file_fat_detectfs(void) return 0; } -int file_fat_ls(const char *dir) -{ - fsdata fsdata; - fat_itr itrblock, *itr = &itrblock; - int files = 0, dirs = 0; - int ret; - - ret = fat_itr_root(itr, &fsdata); - if (ret) - return ret; - - ret = fat_itr_resolve(itr, dir, TYPE_DIR); - if (ret) - return ret; - - while (fat_itr_next(itr)) { - if (fat_itr_isdir(itr)) { - printf("%s/\n", itr->name); - dirs++; - } else { - printf(" %8u %s\n", - FAT2CPU32(itr->dent->size), - itr->name); - files++; - } - } - - printf("\n%d file(s), %d dir(s)\n\n", files, dirs); - - return 0; -} - int fat_exists(const char *filename) { fsdata fsdata; diff --git a/fs/fs.c b/fs/fs.c index fc0c953fcb..3481229aa6 100644 --- a/fs/fs.c +++ b/fs/fs.c @@ -37,6 +37,35 @@ static inline int fs_ls_unsupported(const char *dirname) return -1; } +/* generic implementation of ls in terms of opendir/readdir/closedir */ +__maybe_unused +static int fs_ls_generic(const char *dirname) +{ + struct fs_dir_stream *dirs; + struct fs_dirent *dent; + int nfiles = 0, ndirs = 0; + + dirs = fs_opendir(dirname); + if (!dirs) + return -errno; + + while ((dent = fs_readdir(dirs))) { + if (dent->type == FS_DT_DIR) { + printf("%s/\n", dent->name); + ndirs++; + } else { + printf(" %8lld %s\n", dent->size, dent->name); + nfiles++; + } + } + + fs_closedir(dirs); + + printf("\n%d file(s), %d dir(s)\n\n", nfiles, ndirs); + + return 0; +} + static inline int fs_exists_unsupported(const char *filename) { return 0; @@ -123,7 +152,7 @@ static struct fstype_info fstypes[] = { .null_dev_desc_ok = false, .probe = fat_set_blk_dev, .close = fat_close, - .ls = file_fat_ls, + .ls = fs_ls_generic, .exists = fat_exists, .size = fat_size, .read = fat_read_file, @@ -133,7 +162,9 @@ static struct fstype_info fstypes[] = { .write = fs_write_unsupported, #endif .uuid = fs_uuid_unsupported, - .opendir = fs_opendir_unsupported, + .opendir = fat_opendir, + .readdir = fat_readdir, + .closedir = fat_closedir, }, #endif #ifdef CONFIG_FS_EXT4 diff --git a/include/fat.h b/include/fat.h index b255ce5337..83cd90017e 100644 --- a/include/fat.h +++ b/include/fat.h @@ -11,6 +11,7 @@ #define _FAT_H_ #include +#include #define CONFIG_SUPPORT_VFAT /* Maximum Long File Name length supported here is 128 UTF-16 code units */ @@ -179,7 +180,6 @@ static inline u32 clust_to_sect(fsdata *fsdata, u32 clust) } int file_fat_detectfs(void); -int file_fat_ls(const char *dir); int fat_exists(const char *filename); int fat_size(const char *filename, loff_t *size); int file_fat_read_at(const char *filename, loff_t pos, void *buffer, @@ -192,5 +192,8 @@ int file_fat_write(const char *filename, void *buf, loff_t offset, loff_t len, loff_t *actwrite); int fat_read_file(const char *filename, void *buf, loff_t offset, loff_t len, loff_t *actread); +int fat_opendir(const char *filename, struct fs_dir_stream **dirsp); +int fat_readdir(struct fs_dir_stream *dirs, struct fs_dirent **dentp); +void fat_closedir(struct fs_dir_stream *dirs); void fat_close(void); #endif /* _FAT_H_ */ -- 2.13.5 ___ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot
[U-Boot] [PATCH v3 2/9] fs/fat: introduce new director iterators
Untangle directory traversal into a simple iterator, to replace the existing multi-purpose do_fat_read_at() + get_dentfromdir(). Signed-off-by: Rob Clark Reviewed-by: Łukasz Majewski --- fs/fat/fat.c | 356 +- include/fat.h | 7 ++ 2 files changed, 360 insertions(+), 3 deletions(-) diff --git a/fs/fat/fat.c b/fs/fat/fat.c index e1c0a15dc7..ee2bbe38f1 100644 --- a/fs/fat/fat.c +++ b/fs/fat/fat.c @@ -812,7 +812,6 @@ static int get_fs_info(fsdata *mydata) { boot_sector bs; volume_info volinfo; - __u32 root_cluster = 0; int ret; ret = read_bootsectandvi(&bs, &volinfo, &mydata->fatsize); @@ -822,7 +821,6 @@ static int get_fs_info(fsdata *mydata) } if (mydata->fatsize == 32) { - root_cluster = bs.root_cluster; mydata->fatlength = bs.fat32_length; } else { mydata->fatlength = bs.fat_length; @@ -843,6 +841,7 @@ static int get_fs_info(fsdata *mydata) if (mydata->fatsize == 32) { mydata->data_begin = mydata->rootdir_sect - (mydata->clust_size * 2); + mydata->root_cluster = bs.root_cluster; } else { mydata->rootdir_size = ((bs.dir_entries[1] * (int)256 + bs.dir_entries[0]) * @@ -851,6 +850,9 @@ static int get_fs_info(fsdata *mydata) mydata->data_begin = mydata->rootdir_sect + mydata->rootdir_size - (mydata->clust_size * 2); + mydata->root_cluster = (mydata->rootdir_sect - + mydata->data_begin) / + mydata->clust_size; } mydata->fatbufnum = -1; @@ -868,7 +870,7 @@ static int get_fs_info(fsdata *mydata) mydata->fatsize, mydata->fat_sect, mydata->fatlength); debug("Rootdir begins at cluster: %d, sector: %d, offset: %x\n" "Data begins at: %d\n", - root_cluster, + mydata->root_cluster, mydata->rootdir_sect, mydata->rootdir_sect * mydata->sect_size, mydata->data_begin); debug("Sector size: %d, cluster size: %d\n", mydata->sect_size, @@ -1245,6 +1247,354 @@ exit: return ret; } + +/* + * Directory iterator, to simplify filesystem traversal + * + * Implements an iterator pattern to traverse directory tables, + * transparently handling directory tables split across multiple + * clusters, and the difference between FAT12/FAT16 root directory + * (contiguous) and subdirectories + FAT32 root (chained). + * + * Rough usage: + * + * for (fat_itr_root(&itr, fsdata); fat_itr_next(&itr); ) { + * // to traverse down to a subdirectory pointed to by + * // current iterator position: + * fat_itr_child(&itr, &itr); + * } + * + * For more complete example, see fat_itr_resolve() + */ + +typedef struct { + fsdata*fsdata;/* filesystem parameters */ + unsigned clust; /* current cluster */ + intlast_cluster; /* set once we've read last cluster */ + intis_root; /* is iterator at root directory */ + intremaining; /* remaining dent's in current cluster */ + + /* current iterator position values: */ + dir_entry *dent; /* current directory entry */ + char l_name[VFAT_MAXLEN_BYTES];/* long (vfat) name */ + char s_name[14];/* short 8.3 name */ + char *name; /* l_name if there is one, else s_name */ + + /* storage for current cluster in memory: */ + u8 block[MAX_CLUSTSIZE] __aligned(ARCH_DMA_MINALIGN); +} fat_itr; + +static int fat_itr_isdir(fat_itr *itr); + +/** + * fat_itr_root() - initialize an iterator to start at the root + * directory + * + * @itr: iterator to initialize + * @fsdata: filesystem data for the partition + * @return 0 on success, else -errno + */ +static int fat_itr_root(fat_itr *itr, fsdata *fsdata) +{ + if (get_fs_info(fsdata)) + return -ENXIO; + + itr->fsdata = fsdata; + itr->clust = fsdata->root_cluster; + itr->dent = NULL; + itr->remaining = 0; + itr->last_cluster = 0; + itr->is_root = 1; + + return 0; +} + +/** + * fat_itr_child() - initialize an iterator to descend into a sub- + * directory + * + * Initializes 'itr' to iterate the contents of the directory at + * the current cursor position of 'parent'. It is an error to + * call this if the current cursor of 'parent' is pointing at a + * regular file. + * + * Note that 'itr' and 'parent' can be the same pointer if you do + * not need to preserve 'parent' after this call, which is useful + * for traversing directory structure to resolve a file/directory. + * + * @itr: iterator to initialize + * @
Re: [U-Boot] VU#166743: Das U-Boot AES-CBC encryption
On Sat, Sep 09, 2017 at 09:29:45AM -0700, Blibbet wrote: > I apologize if I missed it, but I haven't see any mention of this recent > vulnerability here, excerpts below. > > http://www.kb.cert.org/vuls/id/166743 > > -snip- > Vulnerability Note VU#166743 > > Das U-Boot AES-CBC encryption implementation contains multiple > vulnerabilities > > Original Release date: 08 Sep 2017 > > Das U-Boot is a device bootloader that can read its configuration from > an AES encrypted file. For devices utilizing this environment encryption > mode, U-Boot's use of a zero initialization vector and improper handling > of an error condition may allow attacks against the underlying > cryptographic implementation and allow an attacker to decrypt the data. > > An attacker with physical access to the device may be able to decrypt > the device's contents. > > The CERT/CC is currently unaware of a practical solution to this problem. > -snip- So, I mentioned this in the patch that migrated the option to Kconfig and marked it deprecated, and I plan to mention it in the release notes on Monday. But, this option has no in-tree users and I plan to remove the code in the near term, if no one with the relevant background steps up to re-implement it. Thanks! -- Tom signature.asc Description: Digital signature ___ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot
[U-Boot] Building qemu-x86_64_defconfig fails: u-boot-spl-nodtb.bin of 4, 293, 642, 704 bytes
export BUILD_ROM=y make mrproper make qemu-x86_64_defconfig make results in a file u-boot-spl-nodtb.bin of 4,293,642,704 bytes for git HEAD. The problematic statement is objcopy -O binary -R .start16 -R .resetvec \ spl/u-boot-spl spl/u-boot-spl-nodtb.bin spl/u-boot-spl has 2,385,168 bytes. My system is Debian Stretch x86_64. GNU objcopy (GNU Binutils for Debian) 2.28 objdump -h spl/u-boot-spl shows that the section .start16 and .resetvec exist. I have created an upstream bug report https://sourceware.org/bugzilla/show_bug.cgi?id=22120 Best regards Heinrich ___ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot
[U-Boot] [PATCH 0/2] GPT: create block device for guid testing
From: Alison Chaiken Simon Glass asked: > Can you please move this into the Python script so that it is created > automatically and deleted at the end. In this version, the device creation is moved to a Python function that the pytest framework can invoke, and a description of the function is added to README.sandbox. The test of the 'gpt guid' command now creates the device at the start of the test and removes it again at the end. Alison Chaiken (2): GPT: create block device for sandbox testing add pytests for 'gpt guid' command in sandbox board/sandbox/README.sandbox | 5 + test/py/make_test_disk.py| 19 +++ test/py/tests/test_gpt.py| 38 ++ 3 files changed, 62 insertions(+) create mode 100755 test/py/make_test_disk.py create mode 100644 test/py/tests/test_gpt.py -- 2.14.1 ___ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot
[U-Boot] [PATCH 2/2] add pytests for 'gpt guid' command in sandbox
From: Alison Chaiken Run unit tests for the 'gpt guid' command, making use of the block device created by test/py/make_test_disk.py. Remove this device at the end of the tests. Signed-off-by: Alison Chaiken --- test/py/tests/test_gpt.py | 38 ++ 1 file changed, 38 insertions(+) create mode 100644 test/py/tests/test_gpt.py diff --git a/test/py/tests/test_gpt.py b/test/py/tests/test_gpt.py new file mode 100644 index 00..73f5c50f6c --- /dev/null +++ b/test/py/tests/test_gpt.py @@ -0,0 +1,38 @@ +# Copyright (c) 2017 Alison Chaiken +# +# SPDX-License-Identifier: GPL-2.0 + +# Test GPT manipulation commands. + +import os +import pytest +import u_boot_utils +import make_test_disk + +""" +These tests rely on a 4 MB block device called testdisk.raw +which is automatically removed at the end of the tests. +""" + +@pytest.mark.buildconfigspec('cmd_gpt') +def test_gpt_guid(u_boot_console): +"""Test the gpt guid command.""" + +if u_boot_console.config.buildconfig.get('config_cmd_gpt', 'n') != 'y': +pytest.skip('gpt command not supported') +make_test_disk.makeDisk() +u_boot_console.run_command('host bind 0 testdisk.raw') +output = u_boot_console.run_command('gpt guid host 0') +assert '375a56f7-d6c9-4e81-b5f0-09d41ca89efe' in output + +@pytest.mark.buildconfigspec('cmd_gpt') +def test_gpt_save_guid(u_boot_console): +"""Test the gpt guid command to save GUID into a string.""" + +if u_boot_console.config.buildconfig.get('config_cmd_gpt', 'n') != 'y': +pytest.skip('gpt command not supported') +u_boot_console.run_command('host bind 0 testdisk.raw') +output = u_boot_console.run_command('gpt guid host 0 newguid') +output = u_boot_console.run_command('printenv newguid') +assert '375a56f7-d6c9-4e81-b5f0-09d41ca89efe' in output +os.remove('testdisk.raw') -- 2.14.1 ___ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot
[U-Boot] [PATCH 1/2] GPT: create block device for sandbox testing
From: Alison Chaiken Provide a Python function that creates a small block device for the purpose of testing the cmd/gpt.c or cmd/part.c functions in the u-boot sandbox. Signed-off-by: Alison Chaiken --- board/sandbox/README.sandbox | 5 + test/py/make_test_disk.py| 19 +++ 2 files changed, 24 insertions(+) create mode 100755 test/py/make_test_disk.py diff --git a/board/sandbox/README.sandbox b/board/sandbox/README.sandbox index 9dc2eb09d1..947241e3eb 100644 --- a/board/sandbox/README.sandbox +++ b/board/sandbox/README.sandbox @@ -338,6 +338,11 @@ $> lodev=`sudo losetup -P -f --show ./disk.raw` $> sudo mkfs.vfat -n EFI -v ${lodev}p1 $> sudo mkfs.ext4 -L ROOT -v ${lodev}p2 +or utilize the device described in test/py/make_test_disk.py: + + #!/usr/bin/python + import make_test_disk + make_test_disk.makeDisk() Writing Sandbox Drivers --- diff --git a/test/py/make_test_disk.py b/test/py/make_test_disk.py new file mode 100755 index 00..5288295588 --- /dev/null +++ b/test/py/make_test_disk.py @@ -0,0 +1,19 @@ +# Copyright (c) 2017 Alison Chaiken +# +# SPDX-License-Identifier: GPL-2.0 +# +# Create a block device for testing of 'gpt' and 'part' commands. + +import os + +def makeDisk(): +if (os.path.exists("testdisk.raw")): +os.remove("testdisk.raw") +fd = os.open("testdisk.raw", os.O_RDWR|os.O_CREAT ) +os.ftruncate(fd, 4194304) +os.close(fd) +os.spawnl(os.P_WAIT, "/sbin/sgdisk", "sgdisk", "-U", + "375a56f7-d6c9-4e81-b5f0-09d41ca89efe", "testdisk.raw") +os.spawnl(os.P_WAIT, "/sbin/sgdisk", "sgdisk", "--new=1:2048:2560", "testdisk.raw") +os.spawnl(os.P_WAIT, "/sbin/sgdisk", "sgdisk", "--new=2:4096:4608", "testdisk.raw") +os.spawnl(os.P_WAIT, "/sbin/gdisk", "sgdisk", "-l", "testdisk.raw") -- 2.14.1 ___ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot
[U-Boot] [PATCH 1/1] add pytests for 'gpt rename' and 'gpt swap'
From: Alison Chaiken Add unit tests for the 'gpt rename' and 'gpt swap' commands that rely on the block device created by test/py/make_test_disk.py. Add CONFIG_CMD_GPT_RENAME to the sandbox_defconfig. Remove the testdisk.raw test device at the end of the tests. Signed-off-by: Alison Chaiken --- configs/sandbox_defconfig | 1 + test/py/tests/test_gpt.py | 31 +++ 2 files changed, 32 insertions(+) diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig index 4c4e4809be..e7a61bd61a 100644 --- a/configs/sandbox_defconfig +++ b/configs/sandbox_defconfig @@ -34,6 +34,7 @@ CONFIG_CMD_MX_CYCLIC=y CONFIG_CMD_DEMO=y CONFIG_CMD_GPIO=y CONFIG_CMD_GPT=y +CONFIG_CMD_GPT_RENAME=y CONFIG_CMD_IDE=y CONFIG_CMD_I2C=y CONFIG_CMD_PCI=y diff --git a/test/py/tests/test_gpt.py b/test/py/tests/test_gpt.py index 73f5c50f6c..06f24b66ce 100644 --- a/test/py/tests/test_gpt.py +++ b/test/py/tests/test_gpt.py @@ -35,4 +35,35 @@ def test_gpt_save_guid(u_boot_console): output = u_boot_console.run_command('gpt guid host 0 newguid') output = u_boot_console.run_command('printenv newguid') assert '375a56f7-d6c9-4e81-b5f0-09d41ca89efe' in output + +@pytest.mark.buildconfigspec('cmd_gpt') +def test_gpt_rename_partition(u_boot_console): +"""Test the gpt rename command to write partition names.""" + +if u_boot_console.config.buildconfig.get('config_cmd_gpt_rename', 'n') != 'y': +pytest.skip('gpt rename command not supported') +u_boot_console.run_command('host bind 0 testdisk.raw') +u_boot_console.run_command('gpt rename host 0 1 first') +output = u_boot_console.run_command('gpt read host 0') +assert 'name first' in output +u_boot_console.run_command('gpt rename host 0 2 second') +output = u_boot_console.run_command('gpt read host 0') +assert 'name second' in output + +@pytest.mark.buildconfigspec('cmd_gpt') +def test_gpt_swap_partitions(u_boot_console): +"""Test the gpt swap command to exchange two partition names.""" + +if u_boot_console.config.buildconfig.get('config_cmd_gpt_rename', 'n') != 'y': +pytest.skip('gpt rename command not supported') +if u_boot_console.config.buildconfig.get('config_cmd_part', 'n') != 'y': +pytest.skip('gpt swap test needs CMD_PART') +u_boot_console.run_command('host bind 0 testdisk.raw') +output = u_boot_console.run_command('part list host 0') +assert '0x07ff "first"' in output +assert '0x17ff "second"' in output +u_boot_console.run_command('gpt swap host 0 first second') +output = u_boot_console.run_command('part list host 0') +assert '0x07ff "second"' in output +assert '0x17ff "first"' in output os.remove('testdisk.raw') -- 2.14.1 ___ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot
[U-Boot] [PATCH v2 1/3] add pytests for 'gpt rename' and 'gpt swap'
From: Alison Chaiken On Tue, Sep 5, 2017 at 1:55 AM, Simon Glass wrote: > How about we add this to sandbox_defconfig instead? So done. -- Alison Alison Chaiken (1): add pytests for 'gpt rename' and 'gpt swap' configs/sandbox_defconfig | 1 + test/py/tests/test_gpt.py | 31 +++ 2 files changed, 32 insertions(+) -- 2.14.1 ___ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot