From de7b5a8a1ac0b711db683711b3ccd800e00c4c46 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 1 Jun 2023 10:22:38 -0600 Subject: [PATCH] fs: Create functions to load and allocate a file This functionality current sits in bootstd, but it is more generally useful. Add a function to load a file into memory, allocating it as needed. Adjust bootstd to use this version. Note: Tests are added in the subsequent patch which converts the 'cat' command to use this function. Signed-off-by: Simon Glass --- boot/bootmeth-uclass.c | 30 ++-------------------- fs/fs.c | 58 ++++++++++++++++++++++++++++++++++++++++++ include/fs.h | 38 +++++++++++++++++++++++++++ 3 files changed, 98 insertions(+), 28 deletions(-) diff --git a/boot/bootmeth-uclass.c b/boot/bootmeth-uclass.c index 3b3e0614da..701ee8ad1c 100644 --- a/boot/bootmeth-uclass.c +++ b/boot/bootmeth-uclass.c @@ -301,32 +301,6 @@ int bootmeth_try_file(struct bootflow *bflow, struct blk_desc *desc, return 0; } -static int alloc_file(const char *fname, uint size, void **bufp) -{ - loff_t bytes_read; - ulong addr; - char *buf; - int ret; - - buf = malloc(size + 1); - if (!buf) - return log_msg_ret("buf", -ENOMEM); - addr = map_to_sysmem(buf); - - ret = fs_read(fname, addr, 0, size, &bytes_read); - if (ret) { - free(buf); - return log_msg_ret("read", ret); - } - if (size != bytes_read) - return log_msg_ret("bread", -EIO); - buf[size] = '\0'; - - *bufp = buf; - - return 0; -} - int bootmeth_alloc_file(struct bootflow *bflow, uint size_limit, uint align) { void *buf; @@ -338,7 +312,7 @@ int bootmeth_alloc_file(struct bootflow *bflow, uint size_limit, uint align) if (size > size_limit) return log_msg_ret("chk", -E2BIG); - ret = alloc_file(bflow->fname, bflow->size, &buf); + ret = fs_read_alloc(bflow->fname, bflow->size, align, &buf); if (ret) return log_msg_ret("all", ret); @@ -374,7 +348,7 @@ int bootmeth_alloc_other(struct bootflow *bflow, const char *fname, if (ret) return log_msg_ret("fs", ret); - ret = alloc_file(path, size, &buf); + ret = fs_read_alloc(path, size, 0, &buf); if (ret) return log_msg_ret("all", ret); diff --git a/fs/fs.c b/fs/fs.c index 8324b4a22f..2b815b1db0 100644 --- a/fs/fs.c +++ b/fs/fs.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -26,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -1008,3 +1010,59 @@ int do_fs_types(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[]) puts("\n"); return CMD_RET_SUCCESS; } + +int fs_read_alloc(const char *fname, ulong size, uint align, void **bufp) +{ + loff_t bytes_read; + ulong addr; + char *buf; + int ret; + + buf = memalign(align, size + 1); + if (!buf) + return log_msg_ret("buf", -ENOMEM); + addr = map_to_sysmem(buf); + + ret = fs_read(fname, addr, 0, size, &bytes_read); + if (ret) { + free(buf); + return log_msg_ret("read", ret); + } + if (size != bytes_read) + return log_msg_ret("bread", -EIO); + buf[size] = '\0'; + + *bufp = buf; + + return 0; +} + +int fs_load_alloc(const char *ifname, const char *dev_part_str, + const char *fname, ulong max_size, ulong align, void **bufp, + ulong *sizep) +{ + loff_t size; + void *buf; + int ret; + + if (fs_set_blk_dev(ifname, dev_part_str, FS_TYPE_ANY)) + return log_msg_ret("set", -ENOMEDIUM); + + ret = fs_size(fname, &size); + if (ret) + return log_msg_ret("sz", -ENOENT); + + if (size >= (max_size ?: SZ_1G)) + return log_msg_ret("sz", -E2BIG); + + if (fs_set_blk_dev(ifname, dev_part_str, FS_TYPE_ANY)) + return log_msg_ret("set", -ENOMEDIUM); + + ret = fs_read_alloc(fname, size, align, &buf); + if (ret) + return log_msg_ret("al", ret); + *sizep = size; + *bufp = buf; + + return 0; +} diff --git a/include/fs.h b/include/fs.h index 8370d88cb2..e341a0ed01 100644 --- a/include/fs.h +++ b/include/fs.h @@ -300,4 +300,42 @@ int do_fs_type(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); */ int do_fs_types(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[]); +/** + * fs_read_alloc() - Allocate space for a file and read it + * + * You must call fs_set_blk_dev() or a similar function before calling this, + * since that sets up the block device to use. + * + * The file is terminated with a nul character + * + * @fname: Filename to read + * @size: Size of file to read (must be correct!) + * @align: Alignment to use for memory allocation (0 for default) + * @bufp: On success, returns the allocated buffer with the nul-terminated file + * in it + * Return: 0 if OK, -ENOMEM if out of memory, -EIO if read failed + */ +int fs_read_alloc(const char *fname, ulong size, uint align, void **bufp); + +/** + * fs_load_alloc() - Load a file into allocated space + * + * The file is terminated with a nul character + * + * @ifname: Interface name to read from (e.g. "mmc") + * @dev_part_str: Device and partition string (e.g. "1:2") + * @fname: Filename to read + * @max_size: Maximum allowed size for the file (use 0 for 1GB) + * @align: Alignment to use for memory allocation (0 for default) + * @bufp: On success, returns the allocated buffer with the nul-terminated file + * in it + * @sizep: On success, returns the size of the file + * Return: 0 if OK, -ENOMEM if out of memory, -ENOENT if the file does not + * exist, -ENOMEDIUM if the device does not exist, -E2BIG if the file is too + * large (greater than @max_size), -EIO if read failed + */ +int fs_load_alloc(const char *ifname, const char *dev_part_str, + const char *fname, ulong max_size, ulong align, void **bufp, + ulong *sizep); + #endif /* _FS_H */ -- 2.39.5