Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/1.2/patches/2221473/?format=api
{ "id": 2221473, "url": "http://patchwork.ozlabs.org/api/1.2/patches/2221473/?format=api", "web_url": "http://patchwork.ozlabs.org/project/uboot/patch/20260409133303.31875-3-ansuelsmth@gmail.com/", "project": { "id": 18, "url": "http://patchwork.ozlabs.org/api/1.2/projects/18/?format=api", "name": "U-Boot", "link_name": "uboot", "list_id": "u-boot.lists.denx.de", "list_email": "u-boot@lists.denx.de", "web_url": null, "scm_url": null, "webscm_url": null, "list_archive_url": "", "list_archive_url_format": "", "commit_url_format": "" }, "msgid": "<20260409133303.31875-3-ansuelsmth@gmail.com>", "list_archive_url": null, "date": "2026-04-09T13:32:58", "name": "[v6,2/6] misc: fs_loader: reorganize and split to FS loader and FW UCLASS", "commit_ref": null, "pull_url": null, "state": "new", "archived": false, "hash": "2c08fb841452450ab1fb1f71feab6ecec3bdf1a0", "submitter": { "id": 71108, "url": "http://patchwork.ozlabs.org/api/1.2/people/71108/?format=api", "name": "Christian Marangi", "email": "ansuelsmth@gmail.com" }, "delegate": { "id": 3651, "url": "http://patchwork.ozlabs.org/api/1.2/users/3651/?format=api", "username": "trini", "first_name": "Tom", "last_name": "Rini", "email": "trini@ti.com" }, "mbox": "http://patchwork.ozlabs.org/project/uboot/patch/20260409133303.31875-3-ansuelsmth@gmail.com/mbox/", "series": [ { "id": 499303, "url": "http://patchwork.ozlabs.org/api/1.2/series/499303/?format=api", "web_url": "http://patchwork.ozlabs.org/project/uboot/list/?series=499303", "date": "2026-04-09T13:32:56", "name": "misc: fs_loader: reorg and split to FS and FW loader + FIP loader", "version": 6, "mbox": "http://patchwork.ozlabs.org/series/499303/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/2221473/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/2221473/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "<u-boot-bounces@lists.denx.de>", "X-Original-To": "incoming@patchwork.ozlabs.org", "Delivered-To": "patchwork-incoming@legolas.ozlabs.org", "Authentication-Results": [ "legolas.ozlabs.org;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256\n header.s=20251104 header.b=gnJ6Plcj;\n\tdkim-atps=neutral", "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de\n (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de;\n envelope-from=u-boot-bounces@lists.denx.de; receiver=patchwork.ozlabs.org)", "phobos.denx.de;\n dmarc=pass (p=none dis=none) header.from=gmail.com", "phobos.denx.de;\n spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de", "phobos.denx.de;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=gmail.com header.i=@gmail.com header.b=\"gnJ6Plcj\";\n\tdkim-atps=neutral", "phobos.denx.de;\n dmarc=pass (p=none dis=none) header.from=gmail.com", "phobos.denx.de;\n spf=pass smtp.mailfrom=ansuelsmth@gmail.com" ], "Received": [ "from phobos.denx.de (phobos.denx.de\n [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4fs19K6npRz1yCv\n\tfor <incoming@patchwork.ozlabs.org>; Thu, 09 Apr 2026 23:33:41 +1000 (AEST)", "from h2850616.stratoserver.net (localhost [IPv6:::1])\n\tby phobos.denx.de (Postfix) with ESMTP id C1E0D84198;\n\tThu, 9 Apr 2026 15:33:25 +0200 (CEST)", "by phobos.denx.de (Postfix, from userid 109)\n id 1308384198; Thu, 9 Apr 2026 15:33:25 +0200 (CEST)", "from mail-wm1-x331.google.com (mail-wm1-x331.google.com\n [IPv6:2a00:1450:4864:20::331])\n (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits))\n (No client certificate requested)\n by phobos.denx.de (Postfix) with ESMTPS id 854FE8414B\n for <u-boot@lists.denx.de>; Thu, 9 Apr 2026 15:33:22 +0200 (CEST)", "by mail-wm1-x331.google.com with SMTP id\n 5b1f17b1804b1-488b0046078so9822995e9.1\n for <u-boot@lists.denx.de>; Thu, 09 Apr 2026 06:33:22 -0700 (PDT)", "from Ansuel-XPS24 (host-82-61-192-155.retail.telecomitalia.it.\n [82.61.192.155]) by smtp.googlemail.com with ESMTPSA id\n 5b1f17b1804b1-488ccf9b919sm52876215e9.0.2026.04.09.06.33.19\n (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n Thu, 09 Apr 2026 06:33:21 -0700 (PDT)" ], "X-Spam-Checker-Version": "SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de", "X-Spam-Level": "", "X-Spam-Status": "No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED,\n DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM,\n RCVD_IN_DNSWL_BLOCKED,SPF_HELO_NONE,SPF_PASS autolearn=ham\n autolearn_force=no version=3.4.2", "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=gmail.com; s=20251104; t=1775741602; x=1776346402; darn=lists.denx.de;\n h=content-transfer-encoding:mime-version:references:in-reply-to\n :message-id:date:subject:to:from:from:to:cc:subject:date:message-id\n :reply-to; bh=XPT2Y0qazd2UuWADhhKiUUlwa+WZ1JjO9WZObS3sdz8=;\n b=gnJ6Plcj2nqadJmiI8ZUjNHBPmF/7R7W2qAAUWenOzbdz9c4Da0dUhN62o43omj0zW\n xZk2rKuxSuEnLm2cSHG6DRBVTHIZMR9JrutfhOHPMFCWbLVCqx3+tRgO8TjazH/tkROB\n mVU3/EpROaqiO66/oWMiK36uUELYf6kbSc/IePKzMyVlymq/8XEvhA8jny8Qa+TXDmL+\n a4a0Lo8m3oSOD31JatApaz0PKdgsxPoHP7Xzb/NwhIKt0LRfoVcK2OnGbDscZf8UVZ/q\n WrUAaX4tZrM62rtzSxf1+tq5zT6xgY5XznRs25Fn6x1aJIRtaYV1/KoG+zTKaYogDO0z\n T0kQ==", "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20251104; t=1775741602; x=1776346402;\n h=content-transfer-encoding:mime-version:references:in-reply-to\n :message-id:date:subject:to:from:x-gm-gg:x-gm-message-state:from:to\n :cc:subject:date:message-id:reply-to;\n bh=XPT2Y0qazd2UuWADhhKiUUlwa+WZ1JjO9WZObS3sdz8=;\n b=hXUySMmi6M/q6GFyp/TcmrgKWuHRi6NukfLV4AzpdaROq/VdrPfoM6M4/dpCIJOjbF\n 4OWIJCxf/RZezdS0gcHO3RzGBbyElD4fSe88R1gnKFsgcEl/mLAnfiExFNex7m5eNvIN\n As2BhNOtMynraONywLjhV/oDwY3REvcSLKecKntf6Lc9uGg6p79fvzAiQlJG0ayctIrM\n WuBd3dkgykn45Mw7NJKL0SlSeC+M3fZk9RP4Br6emyb6mX09xNIgtc413klQfAVogWRl\n aecCCRjKKzfTb9juZMBkQP8KQlvagxCdRRMth372GuZxJI1mr4D8bmTvFC7jBlibMURR\n P13Q==", "X-Forwarded-Encrypted": "i=1;\n AJvYcCWBYbPHKXowj3LwGWJy8cE1RmEty0xbVAx1HLz6XJIUU9V6JjUvn0LJY5V9A0r07HM9rrUNKNs=@lists.denx.de", "X-Gm-Message-State": "AOJu0Yykf8QM6b0Vvdq7+s42sSr2uyNLMXo/63AeOjclHZwROp5uHDQb\n NqTF3sY73lLi8r+ARsP3oqefwh1VGkUDcI0+N0RyfvdJ6dDOU6oXZhtC", "X-Gm-Gg": "AeBDietaogUg41wtt6BOBisod60fXEgosEjYBT4FlEX+9qVPYoe+L3xYZWLcIj0zDlR\n DO/o2XFqJBtLOuT6cFmoj1XDMReRg+9UMgYO7U671vTODykz3WFa2o0UjmQh7CbRD7N3VissO9E\n 4O6oS5wQY/RdUflRe8/JgfINpHnbUB3e409IJdvUe3SfTZPwEHM+W5G1CBa+79vaiT44JZGJR9a\n ONuF0TzMkpcvqYy0lSWDNfheJNQQVKI99Zbng+/4PlBweqNI1TnhEfluDPPzt80Uz0ql9x3DEMR\n jLH6WdFxvVwoQ8ocVu6mmcct/SLvxOdRmxfwHlZdbvl8DLgDPem6/LFOY6JfX6ffbiJSgGEzpp2\n DcZPLyEA7bNHG1UK+Hm15xPtezB9qy4dB/E2WrP0ESFUgmMp4CoFhUQDp/HqLzvS7Ho73in60Nj\n zrm5sMT3Puoaqsa1K1iDFxjDGS1EpLmFPLsPN+l6PEAxS5o5gjjfuzPQesMfAJKd+LkG9Wfew8n\n BTiXfp7iw==", "X-Received": "by 2002:a05:600c:3b23:b0:485:17a7:b9c7 with SMTP id\n 5b1f17b1804b1-488996ecd50mr328962855e9.10.1775741601490;\n Thu, 09 Apr 2026 06:33:21 -0700 (PDT)", "From": "Christian Marangi <ansuelsmth@gmail.com>", "To": "Tom Rini <trini@konsulko.com>, Simon Glass <sjg@chromium.org>,\n Christian Marangi <ansuelsmth@gmail.com>,\n Casey Connolly <casey.connolly@linaro.org>,\n Quentin Schulz <quentin.schulz@cherry.de>, Peng Fan <peng.fan@nxp.com>,\n Kever Yang <kever.yang@rock-chips.com>,\n Heinrich Schuchardt <xypron.glpk@gmx.de>,\n Mateus Lima Alves <mateuslima.ti@gmail.com>,\n Jamie Gibbons <jamie.gibbons@microchip.com>,\n Neha Malcom Francis <n-francis@ti.com>,\n Justin Klaassen <justin@tidylabs.net>,\n Leo Yu-Chi Liang <ycliang@andestech.com>,\n Weijie Gao <weijie.gao@mediatek.com>,\n Marek Vasut <marek.vasut+renesas@mailbox.org>,\n \"Lucien.Jheng\" <lucienzx159@gmail.com>, u-boot@lists.denx.de", "Subject": "[PATCH v6 2/6] misc: fs_loader: reorganize and split to FS loader and\n FW UCLASS", "Date": "Thu, 9 Apr 2026 15:32:58 +0200", "Message-ID": "<20260409133303.31875-3-ansuelsmth@gmail.com>", "X-Mailer": "git-send-email 2.53.0", "In-Reply-To": "<20260409133303.31875-1-ansuelsmth@gmail.com>", "References": "<20260409133303.31875-1-ansuelsmth@gmail.com>", "MIME-Version": "1.0", "Content-Transfer-Encoding": "8bit", "X-BeenThere": "u-boot@lists.denx.de", "X-Mailman-Version": "2.1.39", "Precedence": "list", "List-Id": "U-Boot discussion <u-boot.lists.denx.de>", "List-Unsubscribe": "<https://lists.denx.de/options/u-boot>,\n <mailto:u-boot-request@lists.denx.de?subject=unsubscribe>", "List-Archive": "<https://lists.denx.de/pipermail/u-boot/>", "List-Post": "<mailto:u-boot@lists.denx.de>", "List-Help": "<mailto:u-boot-request@lists.denx.de?subject=help>", "List-Subscribe": "<https://lists.denx.de/listinfo/u-boot>,\n <mailto:u-boot-request@lists.denx.de?subject=subscribe>", "Errors-To": "u-boot-bounces@lists.denx.de", "Sender": "\"U-Boot\" <u-boot-bounces@lists.denx.de>", "X-Virus-Scanned": "clamav-milter 0.103.8 at phobos.denx.de", "X-Virus-Status": "Clean" }, "content": "In preparation to the introduction of variant of the FS loader,\nreorganize and split the driver to generic fw_loader UCLASS and\nspecific fs_loader function. Create a dedicated directory for the loader\nand move the internal structs and functions to a dedicated header file.\nWhile at it also drop some redundant check and rename some variables as we\nare updating the code for the UCLASS rework.\n\nThis will permit to reuse all the property and logic of FS loader\nwith container that are not exactly a readable filesystem.\n\nSigned-off-by: Christian Marangi <ansuelsmth@gmail.com>\n---\n drivers/misc/Kconfig | 5 +\n drivers/misc/Makefile | 2 +-\n drivers/misc/fs_loader.c | 328 ----------------------\n drivers/misc/fw_loader/Makefile | 4 +\n drivers/misc/fw_loader/fs_loader.c | 186 ++++++++++++\n drivers/misc/fw_loader/fw_loader-uclass.c | 147 ++++++++++\n drivers/misc/fw_loader/internal.h | 73 +++++\n include/dm/uclass-id.h | 2 +-\n include/fs_loader.h | 47 +---\n include/fw_loader.h | 19 ++\n 10 files changed, 438 insertions(+), 375 deletions(-)\n delete mode 100644 drivers/misc/fs_loader.c\n create mode 100644 drivers/misc/fw_loader/Makefile\n create mode 100644 drivers/misc/fw_loader/fs_loader.c\n create mode 100644 drivers/misc/fw_loader/fw_loader-uclass.c\n create mode 100644 drivers/misc/fw_loader/internal.h", "diff": "diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig\nindex b2dfc7f5b663..9b181339c468 100644\n--- a/drivers/misc/Kconfig\n+++ b/drivers/misc/Kconfig\n@@ -612,8 +612,12 @@ config MPC83XX_SERDES\n \thelp\n \t Support for serdes found on MPC83xx SoCs.\n \n+config FW_LOADER_UCLASS\n+\tbool\n+\n config FS_LOADER\n \tbool \"Enable loader driver for file system\"\n+\tselect FW_LOADER_UCLASS\n \thelp\n \t This is file system generic loader which can be used to load\n \t the file image from the storage into target such as memory.\n@@ -623,6 +627,7 @@ config FS_LOADER\n \n config SPL_FS_LOADER\n \tbool \"Enable loader driver for file system in SPL\"\n+\tselect FW_LOADER_UCLASS\n \tdepends on SPL\n \thelp\n \t This is file system generic loader which can be used to load\ndiff --git a/drivers/misc/Makefile b/drivers/misc/Makefile\nindex e2170212e5ad..5a3e368767c2 100644\n--- a/drivers/misc/Makefile\n+++ b/drivers/misc/Makefile\n@@ -36,7 +36,7 @@ obj-$(CONFIG_FSL_DEVICE_DISABLE) += fsl_devdis.o\n obj-$(CONFIG_FSL_IFC) += fsl_ifc.o\n obj-$(CONFIG_FSL_IIM) += fsl_iim.o\n obj-$(CONFIG_FSL_SEC_MON) += fsl_sec_mon.o\n-obj-$(CONFIG_$(PHASE_)FS_LOADER) += fs_loader.o\n+obj-$(CONFIG_FW_LOADER_UCLASS) += fw_loader/\n obj-$(CONFIG_GATEWORKS_SC) += gsc.o\n obj-$(CONFIG_GDSYS_IOEP) += gdsys_ioep.o\n obj-$(CONFIG_GDSYS_RXAUI_CTRL) += gdsys_rxaui_ctrl.o\ndiff --git a/drivers/misc/fs_loader.c b/drivers/misc/fs_loader.c\ndeleted file mode 100644\nindex cd4695b08eea..000000000000\n--- a/drivers/misc/fs_loader.c\n+++ /dev/null\n@@ -1,328 +0,0 @@\n-// SPDX-License-Identifier: GPL-2.0\n- /*\n- * Copyright (C) 2018-2019 Intel Corporation <www.intel.com>\n- *\n- */\n-\n-#define LOG_CATEGORY UCLASS_FS_FIRMWARE_LOADER\n-\n-#include <dm.h>\n-#include <env.h>\n-#include <errno.h>\n-#include <blk.h>\n-#include <fs.h>\n-#include <fs_loader.h>\n-#include <log.h>\n-#include <dm/device-internal.h>\n-#include <dm/root.h>\n-#include <linux/string.h>\n-#include <mapmem.h>\n-#include <malloc.h>\n-#include <spl.h>\n-\n-#ifdef CONFIG_CMD_UBIFS\n-#include <ubi_uboot.h>\n-#endif\n-\n-/**\n- * struct firmware - A place for storing firmware and its attribute data.\n- *\n- * This holds information about a firmware and its content.\n- *\n- * @size: Size of a file\n- * @data: Buffer for file\n- * @priv: Firmware loader private fields\n- * @name: Filename\n- * @offset: Offset of reading a file\n- */\n-struct firmware {\n-\tsize_t size;\n-\tconst u8 *data;\n-\tconst char *name;\n-\tu32 offset;\n-};\n-\n-#ifdef CONFIG_CMD_UBIFS\n-static int mount_ubifs(char *mtdpart, char *ubivol)\n-{\n-\tint ret = ubi_part(mtdpart, NULL);\n-\n-\tif (ret) {\n-\t\tdebug(\"Cannot find mtd partition %s\\n\", mtdpart);\n-\t\treturn ret;\n-\t}\n-\n-\treturn cmd_ubifs_mount(ubivol);\n-}\n-\n-static int umount_ubifs(void)\n-{\n-\treturn cmd_ubifs_umount();\n-}\n-#else\n-static int mount_ubifs(char *mtdpart, char *ubivol)\n-{\n-\tdebug(\"Error: Cannot load image: no UBIFS support\\n\");\n-\treturn -ENOSYS;\n-}\n-#endif\n-\n-static int select_fs_dev(struct device_plat *plat)\n-{\n-\tint ret;\n-\n-\tif (plat->phandlepart.phandle) {\n-\t\tofnode node;\n-\n-\t\tnode = ofnode_get_by_phandle(plat->phandlepart.phandle);\n-\n-\t\tstruct udevice *dev;\n-\n-\t\tret = device_get_global_by_ofnode(node, &dev);\n-\t\tif (!ret) {\n-\t\t\tstruct blk_desc *desc = blk_get_by_device(dev);\n-\t\t\tif (desc) {\n-\t\t\t\tret = fs_set_blk_dev_with_part(desc,\n-\t\t\t\t\tplat->phandlepart.partition);\n-\t\t\t} else {\n-\t\t\t\tdebug(\"%s: No device found\\n\", __func__);\n-\t\t\t\treturn -ENODEV;\n-\t\t\t}\n-\t\t}\n-\t} else if (plat->mtdpart && plat->ubivol) {\n-\t\tret = mount_ubifs(plat->mtdpart, plat->ubivol);\n-\t\tif (ret)\n-\t\t\treturn ret;\n-\n-\t\tret = fs_set_blk_dev(\"ubi\", NULL, FS_TYPE_UBIFS);\n-\t} else {\n-\t\tdebug(\"Error: unsupported storage device.\\n\");\n-\t\treturn -ENODEV;\n-\t}\n-\n-\tif (ret)\n-\t\tdebug(\"Error: could not access storage.\\n\");\n-\n-\treturn ret;\n-}\n-\n-/**\n- * _request_firmware_prepare - Prepare firmware struct.\n- *\n- * @dev: An instance of a driver.\n- * @name: Name of firmware file.\n- * @dbuf: Address of buffer to load firmware into.\n- * @size: Size of buffer.\n- * @offset: Offset of a file for start reading into buffer.\n- *\n- * Return: Negative value if fail, 0 for successful.\n- */\n-static int _request_firmware_prepare(struct udevice *dev,\n-\t\t\t\t const char *name, void *dbuf,\n-\t\t\t\t size_t size, u32 offset)\n-{\n-\tif (!name || name[0] == '\\0')\n-\t\treturn -EINVAL;\n-\n-\tstruct firmware *firmwarep = dev_get_priv(dev);\n-\n-\tif (!firmwarep)\n-\t\treturn -ENOMEM;\n-\n-\tfirmwarep->name = name;\n-\tfirmwarep->offset = offset;\n-\tfirmwarep->data = dbuf;\n-\tfirmwarep->size = size;\n-\n-\treturn 0;\n-}\n-\n-/**\n- * fw_get_filesystem_firmware - load firmware into an allocated buffer.\n- * @dev: An instance of a driver.\n- *\n- * Return: Size of total read, negative value when error.\n- */\n-static int fw_get_filesystem_firmware(struct udevice *dev)\n-{\n-\tloff_t actread = 0;\n-\tchar *storage_interface, *dev_part, *ubi_mtdpart, *ubi_volume;\n-\tint ret;\n-\n-\tstorage_interface = env_get(\"storage_interface\");\n-\tdev_part = env_get(\"fw_dev_part\");\n-\tubi_mtdpart = env_get(\"fw_ubi_mtdpart\");\n-\tubi_volume = env_get(\"fw_ubi_volume\");\n-\n-\tif (storage_interface && dev_part) {\n-\t\tret = fs_set_blk_dev(storage_interface, dev_part, FS_TYPE_ANY);\n-\t} else if (storage_interface && ubi_mtdpart && ubi_volume) {\n-\t\tret = mount_ubifs(ubi_mtdpart, ubi_volume);\n-\t\tif (ret)\n-\t\t\treturn ret;\n-\n-\t\tif (!strcmp(\"ubi\", storage_interface))\n-\t\t\tret = fs_set_blk_dev(storage_interface, NULL,\n-\t\t\t\tFS_TYPE_UBIFS);\n-\t\telse\n-\t\t\tret = -ENODEV;\n-\t} else {\n-\t\tret = select_fs_dev(dev_get_plat(dev));\n-\t}\n-\n-\tif (ret)\n-\t\tgoto out;\n-\n-\tstruct firmware *firmwarep = dev_get_priv(dev);\n-\n-\tif (!firmwarep) {\n-\t\tret = -EINVAL;\n-\t\tgoto out;\n-\t}\n-\n-\tret = fs_read(firmwarep->name, (ulong)map_to_sysmem(firmwarep->data),\n-\t\t\tfirmwarep->offset, firmwarep->size, &actread);\n-\n-\tif (ret) {\n-\t\tdebug(\"Error: %d Failed to read %s from flash %lld != %zu.\\n\",\n-\t\t ret, firmwarep->name, actread, firmwarep->size);\n-\t} else {\n-\t\tret = actread;\n-\t}\n-\n-out:\n-#ifdef CONFIG_CMD_UBIFS\n-\tumount_ubifs();\n-#endif\n-\treturn ret;\n-}\n-\n-/**\n- * request_firmware_into_buf - Load firmware into a previously allocated buffer.\n- * @dev: An instance of a driver.\n- * @name: Name of firmware file.\n- * @buf: Address of buffer to load firmware into.\n- * @size: Size of buffer.\n- * @offset: Offset of a file for start reading into buffer.\n- *\n- * The firmware is loaded directly into the buffer pointed to by @buf.\n- *\n- * Return: Size of total read, negative value when error.\n- */\n-int request_firmware_into_buf(struct udevice *dev,\n-\t\t\t const char *name,\n-\t\t\t void *buf, size_t size, u32 offset)\n-{\n-\tint ret;\n-\n-\tif (!dev)\n-\t\treturn -EINVAL;\n-\n-\tret = _request_firmware_prepare(dev, name, buf, size, offset);\n-\tif (ret < 0) /* error */\n-\t\treturn ret;\n-\n-\tret = fw_get_filesystem_firmware(dev);\n-\n-\treturn ret;\n-}\n-\n-static int fs_loader_of_to_plat(struct udevice *dev)\n-{\n-\tu32 phandlepart[2];\n-\n-\tofnode fs_loader_node = dev_ofnode(dev);\n-\n-\tif (ofnode_valid(fs_loader_node)) {\n-\t\tstruct device_plat *plat;\n-\n-\t\tplat = dev_get_plat(dev);\n-\t\tif (!ofnode_read_u32_array(fs_loader_node,\n-\t\t\t\t\t \"phandlepart\",\n-\t\t\t\t\t phandlepart, 2)) {\n-\t\t\tplat->phandlepart.phandle = phandlepart[0];\n-\t\t\tplat->phandlepart.partition = phandlepart[1];\n-\t\t}\n-\n-\t\tplat->mtdpart = (char *)ofnode_read_string(\n-\t\t\t\t fs_loader_node, \"mtdpart\");\n-\n-\t\tplat->ubivol = (char *)ofnode_read_string(\n-\t\t\t\t fs_loader_node, \"ubivol\");\n-\t}\n-\n-\treturn 0;\n-}\n-\n-static int fs_loader_probe(struct udevice *dev)\n-{\n-#if CONFIG_IS_ENABLED(DM) && CONFIG_IS_ENABLED(BLK)\n-\tint ret;\n-\tstruct device_plat *plat = dev_get_plat(dev);\n-\n-\tif (plat->phandlepart.phandle) {\n-\t\tofnode node = ofnode_get_by_phandle(plat->phandlepart.phandle);\n-\t\tstruct udevice *parent_dev = NULL;\n-\n-\t\tret = device_get_global_by_ofnode(node, &parent_dev);\n-\t\tif (!ret) {\n-\t\t\tstruct udevice *dev;\n-\n-\t\t\tret = blk_get_from_parent(parent_dev, &dev);\n-\t\t\tif (ret) {\n-\t\t\t\tdebug(\"fs_loader: No block device: %d\\n\",\n-\t\t\t\t\tret);\n-\n-\t\t\t\treturn ret;\n-\t\t\t}\n-\t\t}\n-\t}\n-#endif\n-\n-\treturn 0;\n-};\n-\n-static const struct udevice_id fs_loader_ids[] = {\n-\t{ .compatible = \"u-boot,fs-loader\"},\n-\t{ }\n-};\n-\n-U_BOOT_DRIVER(fs_loader) = {\n-\t.name\t\t\t= \"fs-loader\",\n-\t.id\t\t\t= UCLASS_FS_FIRMWARE_LOADER,\n-\t.of_match\t\t= fs_loader_ids,\n-\t.probe\t\t\t= fs_loader_probe,\n-\t.of_to_plat\t= fs_loader_of_to_plat,\n-\t.plat_auto\t= sizeof(struct device_plat),\n-\t.priv_auto\t= sizeof(struct firmware),\n-};\n-\n-static struct device_plat default_plat = { 0 };\n-\n-int get_fs_loader(struct udevice **dev)\n-{\n-\tint ret;\n-\tofnode node = ofnode_get_chosen_node(\"firmware-loader\");\n-\n-\tif (ofnode_valid(node))\n-\t\treturn uclass_get_device_by_ofnode(UCLASS_FS_FIRMWARE_LOADER,\n-\t\t\t\t\t\t node, dev);\n-\n-\t/* Try the first device if none was chosen */\n-\tret = uclass_first_device_err(UCLASS_FS_FIRMWARE_LOADER, dev);\n-\tif (ret != -ENODEV)\n-\t\treturn ret;\n-\n-\t/* Just create a new device */\n-\tret = device_bind(dm_root(), DM_DRIVER_REF(fs_loader), \"default-loader\",\n-\t\t\t &default_plat, ofnode_null(), dev);\n-\tif (ret)\n-\t\treturn ret;\n-\n-\treturn device_probe(*dev);\n-}\n-\n-UCLASS_DRIVER(fs_loader) = {\n-\t.id\t\t= UCLASS_FS_FIRMWARE_LOADER,\n-\t.name\t\t= \"fs-loader\",\n-};\ndiff --git a/drivers/misc/fw_loader/Makefile b/drivers/misc/fw_loader/Makefile\nnew file mode 100644\nindex 000000000000..3d5e9f5b338e\n--- /dev/null\n+++ b/drivers/misc/fw_loader/Makefile\n@@ -0,0 +1,4 @@\n+# SPDX-License-Identifier: GPL-2.0+\n+\n+obj-y += fw_loader-uclass.o\n+obj-$(CONFIG_$(PHASE_)FS_LOADER) += fs_loader.o\ndiff --git a/drivers/misc/fw_loader/fs_loader.c b/drivers/misc/fw_loader/fs_loader.c\nnew file mode 100644\nindex 000000000000..2694111d8396\n--- /dev/null\n+++ b/drivers/misc/fw_loader/fs_loader.c\n@@ -0,0 +1,186 @@\n+// SPDX-License-Identifier: GPL-2.0\n+/*\n+ * Copyright (C) 2018-2019 Intel Corporation <www.intel.com>\n+ *\n+ */\n+\n+#define LOG_CATEGORY UCLASS_FIRMWARE_LOADER\n+\n+#include <dm.h>\n+#include <env.h>\n+#include <errno.h>\n+#include <blk.h>\n+#include <fs.h>\n+#include <fs_loader.h>\n+#include <log.h>\n+#include <dm/device-internal.h>\n+#include <dm/root.h>\n+#include <linux/string.h>\n+#include <mapmem.h>\n+#include <malloc.h>\n+#include <spl.h>\n+\n+#ifdef CONFIG_CMD_UBIFS\n+#include <ubi_uboot.h>\n+#endif\n+\n+#include \"internal.h\"\n+\n+#ifdef CONFIG_CMD_UBIFS\n+static int mount_ubifs(char *mtdpart, char *ubivol)\n+{\n+\tint ret;\n+\n+\tret = generic_fw_loader_ubi_select(mtdpart);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\treturn cmd_ubifs_mount(ubivol);\n+}\n+\n+static int umount_ubifs(void)\n+{\n+\treturn cmd_ubifs_umount();\n+}\n+#else\n+static int mount_ubifs(char *mtdpart, char *ubivol)\n+{\n+\tdebug(\"Error: Cannot load image: no UBIFS support\\n\");\n+\treturn -ENOSYS;\n+}\n+#endif\n+\n+static int select_fs_dev(struct device_plat *plat)\n+{\n+\tint ret;\n+\n+\tif (plat->phandlepart.phandle) {\n+\t\tofnode node;\n+\n+\t\tnode = ofnode_get_by_phandle(plat->phandlepart.phandle);\n+\n+\t\tstruct udevice *dev;\n+\n+\t\tret = device_get_global_by_ofnode(node, &dev);\n+\t\tif (!ret) {\n+\t\t\tstruct blk_desc *desc = blk_get_by_device(dev);\n+\t\t\tif (desc) {\n+\t\t\t\tret = fs_set_blk_dev_with_part(desc,\n+\t\t\t\t\tplat->phandlepart.partition);\n+\t\t\t} else {\n+\t\t\t\tdebug(\"%s: No device found\\n\", __func__);\n+\t\t\t\treturn -ENODEV;\n+\t\t\t}\n+\t\t}\n+\t} else if (plat->mtdpart && plat->ubivol) {\n+\t\tret = mount_ubifs(plat->mtdpart, plat->ubivol);\n+\t\tif (ret)\n+\t\t\treturn ret;\n+\n+\t\tret = fs_set_blk_dev(\"ubi\", NULL, FS_TYPE_UBIFS);\n+\t} else {\n+\t\tdebug(\"Error: unsupported storage device.\\n\");\n+\t\treturn -ENODEV;\n+\t}\n+\n+\tif (ret)\n+\t\tdebug(\"Error: could not access storage.\\n\");\n+\n+\treturn ret;\n+}\n+\n+/**\n+ * fw_get_filesystem_firmware - load firmware into an allocated buffer.\n+ * @dev: An instance of a driver.\n+ *\n+ * Return: Size of total read, negative value when error.\n+ */\n+static int fw_get_filesystem_firmware(struct udevice *dev)\n+{\n+\tchar *storage_interface, *dev_part, *ubi_mtdpart, *ubi_volume;\n+\tstruct firmware *upriv = dev_get_uclass_priv(dev);\n+\tstruct device_plat *plat = dev_get_uclass_plat(dev);\n+\tloff_t actread = 0;\n+\tint ret;\n+\n+\tstorage_interface = env_get(\"storage_interface\");\n+\tdev_part = env_get(\"fw_dev_part\");\n+\tubi_mtdpart = env_get(\"fw_ubi_mtdpart\");\n+\tubi_volume = env_get(\"fw_ubi_volume\");\n+\n+\tif (storage_interface && dev_part) {\n+\t\tret = fs_set_blk_dev(storage_interface, dev_part, FS_TYPE_ANY);\n+\t} else if (storage_interface && ubi_mtdpart && ubi_volume) {\n+\t\tret = mount_ubifs(ubi_mtdpart, ubi_volume);\n+\t\tif (ret)\n+\t\t\treturn ret;\n+\n+\t\tif (!strcmp(\"ubi\", storage_interface))\n+\t\t\tret = fs_set_blk_dev(storage_interface, NULL,\n+\t\t\t\t\t FS_TYPE_UBIFS);\n+\t\telse\n+\t\t\tret = -ENODEV;\n+\t} else {\n+\t\tret = select_fs_dev(plat);\n+\t}\n+\n+\tif (ret)\n+\t\tgoto out;\n+\n+\tret = fs_read(upriv->name, (ulong)map_to_sysmem(upriv->data),\n+\t\t upriv->offset, upriv->size, &actread);\n+\n+\tif (ret) {\n+\t\tdebug(\"Error: %d Failed to read %s from flash %lld != %zu.\\n\",\n+\t\t ret, upriv->name, actread, upriv->size);\n+\t} else {\n+\t\tret = actread;\n+\t}\n+\n+out:\n+#ifdef CONFIG_CMD_UBIFS\n+\tumount_ubifs();\n+#endif\n+\treturn ret;\n+}\n+\n+static const struct fw_loader_ops fs_loader_ops = {\n+\t.get_firmware = fw_get_filesystem_firmware,\n+};\n+\n+static const struct udevice_id fs_loader_ids[] = {\n+\t{ .compatible = \"u-boot,fs-loader\"},\n+\t{ }\n+};\n+\n+U_BOOT_DRIVER(fs_loader) = {\n+\t.name\t\t\t= \"fs-loader\",\n+\t.id\t\t\t= UCLASS_FIRMWARE_LOADER,\n+\t.of_match\t\t= fs_loader_ids,\n+\t.ops\t\t\t= &fs_loader_ops,\n+};\n+\n+static struct device_plat default_plat = { 0 };\n+\n+int get_fs_loader(struct udevice **dev)\n+{\n+\tint ret;\n+\tofnode node = ofnode_get_chosen_node(\"firmware-loader\");\n+\n+\tif (ofnode_valid(node))\n+\t\treturn uclass_get_device_by_ofnode(UCLASS_FIRMWARE_LOADER,\n+\t\t\t\t\t\t node, dev);\n+\n+\t/* Try the first device if none was chosen */\n+\tret = uclass_first_device_err(UCLASS_FIRMWARE_LOADER, dev);\n+\tif (ret != -ENODEV)\n+\t\treturn ret;\n+\n+\t/* Just create a new device */\n+\tret = device_bind(dm_root(), DM_DRIVER_REF(fs_loader), \"default-loader\",\n+\t\t\t &default_plat, ofnode_null(), dev);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\treturn device_probe(*dev);\n+}\ndiff --git a/drivers/misc/fw_loader/fw_loader-uclass.c b/drivers/misc/fw_loader/fw_loader-uclass.c\nnew file mode 100644\nindex 000000000000..16a1fe2d4a65\n--- /dev/null\n+++ b/drivers/misc/fw_loader/fw_loader-uclass.c\n@@ -0,0 +1,147 @@\n+// SPDX-License-Identifier: GPL-2.0\n+/*\n+ * Copyright (C) 2018-2019 Intel Corporation <www.intel.com>\n+ *\n+ */\n+\n+#include <errno.h>\n+#include <blk.h>\n+#include <linux/types.h>\n+#include <dm.h>\n+#include <dm/device.h>\n+#include <fw_loader.h>\n+\n+#ifdef CONFIG_CMD_UBIFS\n+#include <ubi_uboot.h>\n+#endif\n+\n+#include \"internal.h\"\n+\n+#ifdef CONFIG_CMD_UBIFS\n+int generic_fw_loader_ubi_select(char *mtdpart)\n+{\n+\tint ret;\n+\n+\tret = ubi_part(mtdpart, NULL);\n+\tif (ret)\n+\t\tdebug(\"Cannot find mtd partition %s\\n\", mtdpart);\n+\n+\treturn ret;\n+}\n+#else\n+int generic_fw_loader_ubi_select(char *mtdpart)\n+{\n+\tdebug(\"Error: Cannot select ubi partition: no UBIFS support\\n\");\n+\treturn -ENOSYS;\n+}\n+#endif\n+\n+static int fw_loader_pre_probe(struct udevice *dev)\n+{\n+\tstruct device_plat *plat = dev_get_uclass_plat(dev);\n+\tofnode fw_loader_node;\n+\tint ret;\n+\n+\tif (!IS_ENABLED(CONFIG_DM))\n+\t\treturn 0;\n+\n+\tfw_loader_node = dev_ofnode(dev);\n+\tif (ofnode_valid(fw_loader_node)) {\n+\t\tu32 phandlepart[2];\n+\n+\t\tif (!ofnode_read_u32_array(fw_loader_node, \"phandlepart\",\n+\t\t\t\t\t phandlepart, 2)) {\n+\t\t\tplat->phandlepart.phandle = phandlepart[0];\n+\t\t\tplat->phandlepart.partition = phandlepart[1];\n+\t\t}\n+\n+\t\tplat->mtdpart = (char *)ofnode_read_string(fw_loader_node,\n+\t\t\t\t\t\t\t \"mtdpart\");\n+\n+\t\tplat->ubivol = (char *)ofnode_read_string(fw_loader_node,\n+\t\t\t\t\t\t\t \"ubivol\");\n+\t}\n+\n+\tif (plat->phandlepart.phandle) {\n+\t\tofnode node = ofnode_get_by_phandle(plat->phandlepart.phandle);\n+\t\tstruct udevice *parent_dev = NULL;\n+\n+\t\tif (!IS_ENABLED(CONFIG_BLK)) {\n+\t\t\tdebug(\"fw_loader: No block device support\\n\");\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\n+\t\tret = device_get_global_by_ofnode(node, &parent_dev);\n+\t\tif (!ret) {\n+\t\t\tstruct udevice *blk_dev;\n+\n+\t\t\tret = blk_get_from_parent(parent_dev, &blk_dev);\n+\t\t\tif (ret) {\n+\t\t\t\tdebug(\"fw_loader: No block device: %d\\n\",\n+\t\t\t\t ret);\n+\n+\t\t\t\treturn ret;\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\treturn 0;\n+}\n+\n+UCLASS_DRIVER(fw_loader) = {\n+\t.id\t\t= UCLASS_FIRMWARE_LOADER,\n+\t.name\t\t= \"fw_loader\",\n+\t.pre_probe\t= fw_loader_pre_probe,\n+\t.per_device_plat_auto = sizeof(struct device_plat),\n+\t.per_device_auto = sizeof(struct firmware),\n+};\n+\n+/**\n+ * _request_firmware_prepare - Prepare firmware struct.\n+ *\n+ * @dev: An instance of a driver.\n+ * @name: Name of firmware file.\n+ * @dbuf: Address of buffer to load firmware into.\n+ * @size: Size of buffer.\n+ * @offset: Offset of a file for start reading into buffer.\n+ *\n+ * Return: Negative value if fail, 0 for successful.\n+ */\n+static int _request_firmware_prepare(struct udevice *dev,\n+\t\t\t\t const char *name, void *dbuf,\n+\t\t\t\t size_t size, u32 offset)\n+{\n+\tstruct firmware *upriv = dev_get_uclass_priv(dev);\n+\n+\tif (!name || name[0] == '\\0')\n+\t\treturn -EINVAL;\n+\n+\tupriv->name = name;\n+\tupriv->offset = offset;\n+\tupriv->data = dbuf;\n+\tupriv->size = size;\n+\n+\treturn 0;\n+}\n+\n+int request_firmware_into_buf(struct udevice *dev,\n+\t\t\t const char *name,\n+\t\t\t void *buf, size_t size, u32 offset)\n+{\n+\tstruct fw_loader_ops *ops;\n+\tint ret;\n+\n+\tif (!dev)\n+\t\treturn -EINVAL;\n+\n+\tret = _request_firmware_prepare(dev, name, buf, size, offset);\n+\tif (ret < 0) /* error */\n+\t\treturn ret;\n+\n+\tops = fw_loader_get_ops(dev);\n+\n+\tif (!ops->get_firmware)\n+\t\treturn -EOPNOTSUPP;\n+\n+\treturn ops->get_firmware(dev);\n+}\ndiff --git a/drivers/misc/fw_loader/internal.h b/drivers/misc/fw_loader/internal.h\nnew file mode 100644\nindex 000000000000..2f93d0c706b6\n--- /dev/null\n+++ b/drivers/misc/fw_loader/internal.h\n@@ -0,0 +1,73 @@\n+/* SPDX-License-Identifier: GPL-2.0 */\n+/*\n+ * Copyright (C) 2018-2019 Intel Corporation <www.intel.com>\n+ */\n+#ifndef _FW_LOADER_INTERNAL_H_\n+#define _FW_LOADER_INTERNAL_H_\n+\n+/**\n+ * struct phandle_part - A place for storing phandle of node and its partition\n+ *\n+ * This holds information about a phandle of the block device, and its\n+ * partition where the firmware would be loaded from.\n+ *\n+ * @phandle: Phandle of storage device node\n+ * @partition: Partition of block device\n+ */\n+struct phandle_part {\n+\tu32 phandle;\n+\tu32 partition;\n+};\n+\n+/**\n+ * struct fw_loader_ops - driver operations for Firmware Loader uclass\n+ *\n+ * Drivers MUST support these operation. These operations are intended\n+ * to be used by uclass code, not directly from other code.\n+ */\n+struct fw_loader_ops {\n+\t/**\n+\t * get_firmware() - get firmware from Firmware Loader driver\n+\t *\n+\t * @dev:\tFirmware Loader device to read firmware from\n+\t */\n+\tint (*get_firmware)(struct udevice *dev);\n+};\n+\n+#define fw_loader_get_ops(dev)\t((struct fw_loader_ops *)(dev)->driver->ops)\n+\n+/**\n+ * struct device_plat - A place for storing all supported storage devices\n+ *\n+ * This holds information about all supported storage devices for driver use.\n+ *\n+ * @phandlepart: Attribute data for block device.\n+ * @mtdpart: MTD partition for ubi partition.\n+ * @ubivol: UBI volume-name for ubifsmount.\n+ */\n+struct device_plat {\n+\tstruct phandle_part phandlepart;\n+\tchar *mtdpart;\n+\tchar *ubivol;\n+};\n+\n+/**\n+ * struct firmware - A place for storing firmware and its attribute data.\n+ *\n+ * This holds information about a firmware and its content.\n+ *\n+ * @size: Size of a file\n+ * @data: Buffer for file\n+ * @name: Filename\n+ * @offset: Offset of reading a file\n+ */\n+struct firmware {\n+\tsize_t size;\n+\tconst u8 *data;\n+\tconst char *name;\n+\tu32 offset;\n+};\n+\n+int generic_fw_loader_ubi_select(char *mtdpart);\n+\n+#endif\ndiff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h\nindex 36b5d87c304f..5ef3138e6ac7 100644\n--- a/include/dm/uclass-id.h\n+++ b/include/dm/uclass-id.h\n@@ -69,7 +69,7 @@ enum uclass_id {\n \tUCLASS_FIRMWARE,\t/* Firmware */\n \tUCLASS_FPGA,\t\t/* FPGA device */\n \tUCLASS_FUZZING_ENGINE,\t/* Fuzzing engine */\n-\tUCLASS_FS_FIRMWARE_LOADER,\t\t/* Generic loader */\n+\tUCLASS_FIRMWARE_LOADER,\t/* Firmware loader */\n \tUCLASS_FWU_MDATA,\t/* FWU Metadata Access */\n \tUCLASS_GPIO,\t\t/* Bank of general-purpose I/O pins */\n \tUCLASS_HASH,\t\t/* Hash device */\ndiff --git a/include/fs_loader.h b/include/fs_loader.h\nindex 7e16e0f70309..3c64efe1b439 100644\n--- a/include/fs_loader.h\n+++ b/include/fs_loader.h\n@@ -6,52 +6,9 @@\n #ifndef _FS_LOADER_H_\n #define _FS_LOADER_H_\n \n-struct udevice;\n-\n-/**\n- * struct phandle_part - A place for storing phandle of node and its partition\n- *\n- * This holds information about a phandle of the block device, and its\n- * partition where the firmware would be loaded from.\n- *\n- * @phandle: Phandle of storage device node\n- * @partition: Partition of block device\n- */\n-struct phandle_part {\n-\tu32 phandle;\n-\tu32 partition;\n-};\n-\n-/**\n- * struct phandle_part - A place for storing all supported storage devices\n- *\n- * This holds information about all supported storage devices for driver use.\n- *\n- * @phandlepart: Attribute data for block device.\n- * @mtdpart: MTD partition for ubi partition.\n- * @ubivol: UBI volume-name for ubifsmount.\n- */\n-struct device_plat {\n-\tstruct phandle_part phandlepart;\n-\tchar *mtdpart;\n-\tchar *ubivol;\n-};\n+#include <fw_loader.h>\n \n-/**\n- * request_firmware_into_buf - Load firmware into a previously allocated buffer.\n- * @dev: An instance of a driver.\n- * @name: Name of firmware file.\n- * @buf: Address of buffer to load firmware into.\n- * @size: Size of buffer.\n- * @offset: Offset of a file for start reading into buffer.\n- *\n- * The firmware is loaded directly into the buffer pointed to by @buf.\n- *\n- * Return: Size of total read, negative value when error.\n- */\n-int request_firmware_into_buf(struct udevice *dev,\n-\t\t\t const char *name,\n-\t\t\t void *buf, size_t size, u32 offset);\n+struct udevice;\n \n /**\n * get_fs_loader() - Get the chosen filesystem loader\ndiff --git a/include/fw_loader.h b/include/fw_loader.h\nindex 35574482b2b9..56f5e3be6195 100644\n--- a/include/fw_loader.h\n+++ b/include/fw_loader.h\n@@ -1,10 +1,29 @@\n /* SPDX-License-Identifier: GPL-2.0 */\n /*\n+ * Copyright (C) 2018-2019 Intel Corporation <www.intel.com>\n * Copyright (C) 2025 Lucien Jheng <lucienzx159@gmail.com>\n */\n #ifndef _FW_LOADER_H_\n #define _FW_LOADER_H_\n \n+struct udevice;\n+\n+/**\n+ * request_firmware_into_buf - Load firmware into a previously allocated buffer.\n+ * @dev: An instance of a driver.\n+ * @name: Name of firmware file.\n+ * @buf: Address of buffer to load firmware into.\n+ * @size: Size of buffer.\n+ * @offset: Offset of a file for start reading into buffer.\n+ *\n+ * The firmware is loaded directly into the buffer pointed to by @buf.\n+ *\n+ * Return: Size of total read, negative value when error.\n+ */\n+int request_firmware_into_buf(struct udevice *dev,\n+\t\t\t const char *name,\n+\t\t\t void *buf, size_t size, u32 offset);\n+\n /**\n * request_firmware_into_buf_via_script() -\n * Load firmware using a U-Boot script and copy to buffer\n", "prefixes": [ "v6", "2/6" ] }