From patchwork Sun Aug 13 10:45:24 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rob Clark X-Patchwork-Id: 800976 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="JulClYjy"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 3xVb6h3zCTz9sRV for ; Sun, 13 Aug 2017 20:47:40 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id DEC9FC21E71; Sun, 13 Aug 2017 10:46:45 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=-0.0 required=5.0 tests=FREEMAIL_FROM, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, T_DKIM_INVALID autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id 5D224C21E35; Sun, 13 Aug 2017 10:46:42 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id CB931C21E54; Sun, 13 Aug 2017 10:46:15 +0000 (UTC) Received: from mail-qt0-f196.google.com (mail-qt0-f196.google.com [209.85.216.196]) by lists.denx.de (Postfix) with ESMTPS id B129EC21E0B for ; Sun, 13 Aug 2017 10:46:11 +0000 (UTC) Received: by mail-qt0-f196.google.com with SMTP id p3so7392795qtg.5 for ; Sun, 13 Aug 2017 03:46:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=TrnWzxHtv5rDWEOgR8gegj6xHIle9JvU4RvTVE2W5vA=; b=JulClYjylChdSbPbdeBBdsH/YKxjuvDiLs6aQdY/nTVF8fZfCkRbTbQMG4AGyVuTtq Uf/tHpvgkGUlQOWyLqYxZFs0pscN3OIaY4MFIQYFziwc69Y3sCXfsUeusjv6xUG2ydgK er3MNwDLWlSHArABQP1gkhWoAUPoquiWa9HcigDCDycPtuaN+g3YXZJusDGJl3iOyuCz 1pEyNVjFXdrSvrzPMnshYw0hLvTSfV0wQuScA2b28HDx7Mdwo/szCiSZCNTxlz0VhveS Nk41WBFz2aNtHqJs1EkxsXfNtgwA0hWNHyddNGTurSjzzX8DiEjZjfDGs9f7ceyIuXIe nq1w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=TrnWzxHtv5rDWEOgR8gegj6xHIle9JvU4RvTVE2W5vA=; b=qamwEliycqdc0iV1xwqc9k9/8AvD7mR0DC8YXxS4MANhRaCC7MDAq/RacN2EB8rGAP teGgDEFxyDH/DCE6AA8u8OGZuOBXhybsUOEC5AO/86Ll44hwB2yug/1EvQnpF5Qn9zF8 0PsUCyDb7Coka6anZ8pv/s2WzdCEk/lRPayYdeIjy4S2sRQEqlQBZ84uJRJL8HdekP8x /g/GqcgW2PJIs7PnlvC+wkah2U7vDfQ3GT88Ub9V5b7TyQ23nin+4afa99JvjQDWM4r2 QKRIWPafKJw4+lFmE4PHoivWckajfXQO4yqlSoowWHARXmPhe0rdmUIBJMIx/x5wpOD2 P2Gw== X-Gm-Message-State: AHYfb5gAD+Hvrjpwvd7gNPTaKx0ddZK0D+y3dgI+1Jelw+D5itDtCQPK RmT/7kfyIQXqYw1op3Q= X-Received: by 10.200.54.152 with SMTP id a24mr31354805qtc.66.1502621170408; Sun, 13 Aug 2017 03:46:10 -0700 (PDT) Received: from localhost ([2601:184:4780:aac0:25f8:dd96:a084:785a]) by smtp.gmail.com with ESMTPSA id l36sm3473502qte.31.2017.08.13.03.46.08 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Sun, 13 Aug 2017 03:46:09 -0700 (PDT) From: Rob Clark To: U-Boot Mailing List Date: Sun, 13 Aug 2017 06:45:24 -0400 Message-Id: <20170813104531.16407-5-robdclark@gmail.com> X-Mailer: git-send-email 2.13.0 In-Reply-To: <20170813104531.16407-1-robdclark@gmail.com> References: <20170813104531.16407-1-robdclark@gmail.com> Subject: [U-Boot] [PATCH 4/8] fs: add fs_readdir() X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" 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 --- fs/fs.c | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ include/fs.h | 55 +++++++++++++++++++++++++++++++++++++ 2 files changed, 143 insertions(+) diff --git a/fs/fs.c b/fs/fs.c index 595ff1fe69..f9ea3480e9 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,11 @@ static inline int fs_uuid_unsupported(char *uuid_str) return -1; } +static inline int fs_opendir_unsupported(const char *filename, FS_DIR **dirp) +{ + return -EACCES; +} + struct fstype_info { int fstype; char *name; @@ -92,6 +98,9 @@ struct fstype_info { loff_t len, loff_t *actwrite); void (*close)(void); int (*uuid)(char *uuid_str); + int (*opendir)(const char *filename, FS_DIR **dirp); + int (*readdir)(FS_DIR *dirp); + void (*closedir)(FS_DIR *dirp); }; static struct fstype_info fstypes[] = { @@ -112,6 +121,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 +141,7 @@ static struct fstype_info fstypes[] = { .write = fs_write_unsupported, #endif .uuid = ext4fs_uuid, + .opendir = fs_opendir_unsupported, }, #endif #ifdef CONFIG_SANDBOX @@ -146,6 +157,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 +173,7 @@ static struct fstype_info fstypes[] = { .read = ubifs_read, .write = fs_write_unsupported, .uuid = fs_uuid_unsupported, + .opendir = fs_opendir_unsupported, }, #endif { @@ -175,6 +188,7 @@ static struct fstype_info fstypes[] = { .read = fs_read_unsupported, .write = fs_write_unsupported, .uuid = fs_uuid_unsupported, + .opendir = fs_opendir_unsupported, }, }; @@ -228,6 +242,28 @@ int fs_set_blk_dev(const char *ifname, const char *dev_part_str, int fstype) if (!info->probe(fs_dev_desc, &fs_partition)) { fs_type = info->fstype; + fs_dev_part = part; + return 0; + } + } + + return -1; +} + +/* set current blk device w/ blk_desc + partition # */ +int fs_set_blk_dev2(struct blk_desc *desc, int part) +{ + struct fstype_info *info; + int ret, i; + + ret = part_get_info(desc, part, &fs_partition); + if (ret) + return ret; + fs_dev_desc = desc; + + for (i = 0, info = fstypes; i < ARRAY_SIZE(fstypes); i++, info++) { + if (!info->probe(fs_dev_desc, &fs_partition)) { + fs_type = info->fstype; return 0; } } @@ -334,6 +370,58 @@ int fs_write(const char *filename, ulong addr, loff_t offset, loff_t len, return ret; } +FS_DIR *fs_opendir(const char *filename) +{ + struct fstype_info *info = fs_get_info(fs_type); + FS_DIR *dirp = NULL; + int ret; + + ret = info->opendir(filename, &dirp); + fs_close(); + if (ret) { + errno = -ret; + return NULL; + } + + dirp->desc = fs_dev_desc; + dirp->part = fs_dev_part; + + return dirp; +} + +struct fs_dirent *fs_readdir(FS_DIR *dirp) +{ + struct fstype_info *info; + int ret; + + fs_set_blk_dev2(dirp->desc, dirp->part); + info = fs_get_info(fs_type); + + memset(&dirp->dirent, 0, sizeof(dirp->dirent)); + + ret = info->readdir(dirp); + fs_close(); + if (ret) + return NULL; + + return &dirp->dirent;; +} + +void fs_closedir(FS_DIR *dirp) +{ + struct fstype_info *info; + + if (!dirp) + return; + + fs_set_blk_dev2(dirp->desc, dirp->part); + info = fs_get_info(fs_type); + + info->closedir(dirp); + fs_close(); +} + + int do_size(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[], int fstype) { diff --git a/include/fs.h b/include/fs.h index 2f2aca8378..0a6a366078 100644 --- a/include/fs.h +++ b/include/fs.h @@ -26,6 +26,8 @@ */ int fs_set_blk_dev(const char *ifname, const char *dev_part_str, int fstype); +int fs_set_blk_dev2(struct blk_desc *desc, int part); + /* * Print the list of files on the partition previously set by fs_set_blk_dev(), * in directory "dirname". @@ -78,6 +80,59 @@ int fs_read(const char *filename, ulong addr, loff_t offset, loff_t len, int fs_write(const char *filename, ulong addr, loff_t offset, loff_t len, loff_t *actwrite); +/* Add additional FS_DT_* as supported by additional filesystems:*/ +#define FS_DT_DIR 0x4 /* directory */ +#define FS_DT_REG 0x8 /* regular file */ + +/* + * A directory entry. + */ +struct fs_dirent { + unsigned type; /* one of FS_DT_* */ + loff_t size; + char name[256]; +}; + +typedef struct _FS_DIR FS_DIR; + +/* + * fs_opendir - Open a directory + * + * @filename: the path to directory to open + * @return a pointer to the directory stream or NULL on error and errno + * set appropriately + */ +FS_DIR *fs_opendir(const char *filename); + +/* + * fs_readdir - Read the next directory entry in the directory stream. + * + * @dirp: the directory stream + * @return the next directory entry (only valid until next fs_readdir() or + * fs_closedir() call, do not attempt to free()) or NULL if the end of + * the directory is reached. + */ +struct fs_dirent *fs_readdir(FS_DIR *dirp); + +/* + * fs_closedir - close a directory stream + * + * @dirp: the directory stream + */ +void fs_closedir(FS_DIR *dirp); + +/* + * private to fs implementations, would be in fs.c but we need to let + * implementations subclass: + */ + +struct _FS_DIR { + struct fs_dirent dirent; + /* private to fs layer: */ + struct blk_desc *desc; + int part; +}; + /* * Common implementation for various filesystem commands, optionally limited * to a specific filesystem type via the fstype parameter.