get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/1.2/patches/2221478/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 2221478,
    "url": "http://patchwork.ozlabs.org/api/1.2/patches/2221478/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/uboot/patch/20260409133303.31875-6-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-6-ansuelsmth@gmail.com>",
    "list_archive_url": null,
    "date": "2026-04-09T13:33:01",
    "name": "[v6,5/6] misc: fw_loader: introduce FIP loader driver",
    "commit_ref": null,
    "pull_url": null,
    "state": "new",
    "archived": false,
    "hash": "8c391144c047bb865ad10cc8b58f0291f012254d",
    "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-6-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/2221478/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/2221478/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=G8/Ni9x4;\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=\"G8/Ni9x4\";\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 4fs19v5XV9z1yHG\n\tfor <incoming@patchwork.ozlabs.org>; Thu, 09 Apr 2026 23:34:11 +1000 (AEST)",
            "from h2850616.stratoserver.net (localhost [IPv6:::1])\n\tby phobos.denx.de (Postfix) with ESMTP id 7A6CD841D7;\n\tThu,  9 Apr 2026 15:33:30 +0200 (CEST)",
            "by phobos.denx.de (Postfix, from userid 109)\n id 9E6548416F; Thu,  9 Apr 2026 15:33:29 +0200 (CEST)",
            "from mail-wm1-x32b.google.com (mail-wm1-x32b.google.com\n [IPv6:2a00:1450:4864:20::32b])\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 26A51841D7\n for <u-boot@lists.denx.de>; Thu,  9 Apr 2026 15:33:27 +0200 (CEST)",
            "by mail-wm1-x32b.google.com with SMTP id\n 5b1f17b1804b1-488d2079582so5418115e9.2\n for <u-boot@lists.denx.de>; Thu, 09 Apr 2026 06:33:27 -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.24\n (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n Thu, 09 Apr 2026 06:33:25 -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=1775741606; x=1776346406; 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=xi0KjjRHhcT1w5sGmU1735DcovHVbHHPpNF1svMRmX0=;\n b=G8/Ni9x4AYJpnqv4QBscXsi8ZupO0e+/zviJ4F4oE6GbMSPn8gTqF4rYzmrqU8WRZ6\n NCTrOc7MphSsZMiPh18ZHRYpPGIbmtTJIRYV2C1j03z3LckX6ExA0B7HJQJqnKiJgsYF\n +gnDZ0WNOEEdejYnY/P7v4RJS3rTVhecXe3fqkC8XKVBtfeOhDsTKsAdFgpphp2ZOyMK\n afl85JmvwKjvetjgDnVHXsnhnvmF+/Tp+V5I+e6aUJoKkJfj78KRT6C9QMefc5LBrK3U\n ODJviALMD3ruFIvNv1r72JPOiOwn5S0E9bKQ71WU9qzgvKtMOzuOLoEhCXft7pqY+8Xa\n LkjA==",
        "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20251104; t=1775741606; x=1776346406;\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=xi0KjjRHhcT1w5sGmU1735DcovHVbHHPpNF1svMRmX0=;\n b=kQ6Wv/AuU7g2nXP/mbRnoHX2kaytcNaZNHyYG3Vr1dhCjV4zipxPTW5nnTD7hoDNN3\n 2zqTzo+bf1CtR9v/yAGdUHq9Gvscd0yFJ+9AnD1ntWTOcpYK3X6TqI+NA6YFBuj6p4px\n xgRA7ouaYUc9MjUX+tuXYnwq47E3mjrJrwgM6Ay5drG6e/UCJsSUoXdAGxBi4ESNWDK2\n wO2+w1YY0AilMcbw8C3jOrDP2H1GY7pQixVKonNiLUzpji7HtuJxZKkao4wsqgpzUsLp\n yttBBGoiYq+CBm3KK8HVSPaJcsK9nxxOo+R/gf7ub/MMc9avpFiLU0t2OF6F8w9GTnkP\n dYPw==",
        "X-Forwarded-Encrypted": "i=1;\n AJvYcCXnRCezCVyP0E7Zkvg5gBLF8F4AWS0hcgD/53sZNGoz9qyjMQeCVsRwiU9fAcwxgJoQUAvZj1A=@lists.denx.de",
        "X-Gm-Message-State": "AOJu0YyCpNAryPHNbakCM2AxtXN47KLiAyLk2TRVvlmV8z9Gvf666hD9\n Yl5LTf3GQXpPafzppWurnpZMVk7Qow5lyt1d3USlYVj38Adgua9pXrkC",
        "X-Gm-Gg": "AeBDieuqXpvqYqw5uSeOcC/xh7C7uhBBPrE9jk40wkFujrsK8WhlDyhzJqOR9H8+bnh\n xsWMxCgbFFDl+BPe4Sd8U0TuILneMFOtbjbX8GLviDvOwIVFkLZBhemhiEYZasAJMle6o3oca2j\n j+6YCzSihA+CpopaeBUs7ohHEy3fvIlGtU1VCgoi4fAI+Vkz9sHHXYqfRAVltHHKCHWz7Yn1OA7\n nrZxOaPVX2gI3K0GEHsjYUDDOBpWOXVfuDzw+vP4LCkop29yGvBUJDhLr9RfLHVqZtZ32kOH3Bd\n QVNBCwM4I6PT7wC3Nc1t3TpWUfKmbnekEQgrilyqXwaMi8T3r0HGIiy/tPHaJ9iDF9oEJGfDhA7\n 5MERPQFofSjpeW9CPqs22TcesrOBl+fSaFPW40fBpf9pN/QAFuz8SAY4xKe6NvF+yf8Avi5l0yx\n TZ2uHE7sQV/KZ2k0O+xLK50WxqomEupLK6XE5QZF2rBKtbpAlk2E2YcXpBrGedT1mcAQGxGD8=",
        "X-Received": "by 2002:a05:600c:1d86:b0:485:304a:58cd with SMTP id\n 5b1f17b1804b1-488997153c7mr299528425e9.4.1775741606198;\n Thu, 09 Apr 2026 06:33:26 -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 5/6] misc: fw_loader: introduce FIP loader driver",
        "Date": "Thu,  9 Apr 2026 15:33:01 +0200",
        "Message-ID": "<20260409133303.31875-6-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": "Introduce a variant of the FS loader driver to extract images from FIP\nimage. These image can contain additional binary used to init Network\naccelerator or PHY firmware blob.\n\nThe way FIP handle image type is with the usage of UUID.\n\nThis FIP loader driver implement a simple FIP image parser that check\nevery entry for a matching UUID.\n\nSimilar to FS loader, this driver also support both UBI and Block\ndevices.\n\nAlso an additional property is added to handle special case with eMMC\nthat doesn't have a GPT partition and require a global offset to\nreference the FIP partition.\n\nAn example usage of this driver is the following:\n\nEntry in DTS:\n\n\tfs_loader0: fip-loader {\n\t\tbootph-all;\n\t\tcompatible = \"u-boot,fip-loader\";\n\t\tphandlepart = <&mmc0 0>;\n\t\tpartoffset = <0x100>;\n\t};\n\n\tethernet@1fb50000 {\n\t\tfirmware-loader = <&fs_loader0>;\n\t}\n\nFIP loader user:\n\n\t/* get the FW loader from the ethernet node */\n\tget_fw_loader_from_node(dev_ofnode(dev), &fw_loader);\n\n\t/* read the blob identified by \"58704aef-389f-3e52-b475-e0bf2234a6a2\" UUID */\n\trequest_firmware_into_buf(fw_loader, \"58704aef-389f-3e52-b475-e0bf2234a6a2\",\n\t\t\t\t  buf, 261400, 0);\n\nSigned-off-by: Christian Marangi <ansuelsmth@gmail.com>\n---\n drivers/misc/Kconfig                      |  11 +\n drivers/misc/fw_loader/Makefile           |   1 +\n drivers/misc/fw_loader/fip_loader.c       | 544 ++++++++++++++++++++++\n drivers/misc/fw_loader/fw_loader-uclass.c |   3 +\n drivers/misc/fw_loader/internal.h         |   2 +\n 5 files changed, 561 insertions(+)\n create mode 100644 drivers/misc/fw_loader/fip_loader.c",
    "diff": "diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig\nindex 9b181339c468..ee0a9f40d99e 100644\n--- a/drivers/misc/Kconfig\n+++ b/drivers/misc/Kconfig\n@@ -615,6 +615,17 @@ config MPC83XX_SERDES\n config FW_LOADER_UCLASS\n \tbool\n \n+config FIP_LOADER\n+\tbool \"Enable loader driver from FIP partition\"\n+\tselect LIB_UUID\n+\tselect FW_LOADER_UCLASS\n+\thelp\n+\t  This is FIP partition generic loader which can be used to load\n+\t  the file image from the FIP image into target such as memory.\n+\n+\t  The consumer driver would then use this loader to program whatever,\n+\t  ie. the FPGA device/PHY firmware.\n+\n config FS_LOADER\n \tbool \"Enable loader driver for file system\"\n \tselect FW_LOADER_UCLASS\ndiff --git a/drivers/misc/fw_loader/Makefile b/drivers/misc/fw_loader/Makefile\nindex 3d5e9f5b338e..29418a008fb3 100644\n--- a/drivers/misc/fw_loader/Makefile\n+++ b/drivers/misc/fw_loader/Makefile\n@@ -1,4 +1,5 @@\n # SPDX-License-Identifier: GPL-2.0+\n \n obj-y += fw_loader-uclass.o\n+obj-$(CONFIG_FIP_LOADER) += fip_loader.o\n obj-$(CONFIG_$(PHASE_)FS_LOADER) += fs_loader.o\ndiff --git a/drivers/misc/fw_loader/fip_loader.c b/drivers/misc/fw_loader/fip_loader.c\nnew file mode 100644\nindex 000000000000..da1ed98eeb4c\n--- /dev/null\n+++ b/drivers/misc/fw_loader/fip_loader.c\n@@ -0,0 +1,544 @@\n+// SPDX-License-Identifier: GPL-2.0\n+/*\n+ * Copyright (C) 2025 Christian Marangi <ansuelsmth@gmail.com>\n+ *\n+ */\n+\n+#define LOG_CATEGORY UCLASS_FIRMWARE_LOADER\n+\n+#include <dm.h>\n+#include <div64.h>\n+#include <env.h>\n+#include <errno.h>\n+#include <blk.h>\n+#include <fs.h>\n+#include <linux/kernel.h>\n+#include <log.h>\n+#include <mapmem.h>\n+#include <malloc.h>\n+#include <memalign.h>\n+#include <part.h>\n+#include <u-boot/uuid.h>\n+\n+#include \"internal.h\"\n+\n+#define TOC_HEADER_NAME\t0xaa640001\n+\n+struct fip_toc_header {\n+\tu32 name;\n+\tu32 serial_number;\n+\tu64 flags;\n+};\n+\n+struct fip_toc_entry {\n+\tstruct uuid uuid;\n+\tu64 offset_address;\n+\tu64 size;\n+\tu64 flags;\n+};\n+\n+enum fip_storage_interface {\n+\tFIP_STORAGE_INTERFACE_BLK,\n+\tFIP_STORAGE_INTERFACE_UBI,\n+};\n+\n+struct fip_storage_info {\n+\tenum fip_storage_interface storage_interface;\n+\n+\t/* BLK info */\n+\tstruct disk_partition part_info;\n+\tstruct blk_desc *desc;\n+\tunsigned int part_offset;\n+\n+\t/* UBI info */\n+\tchar *ubi_volume;\n+};\n+\n+static bool validate_fip_toc_header(struct fip_toc_header *hdr)\n+{\n+\tif (hdr->name != TOC_HEADER_NAME) {\n+\t\tlog_err(\"Invalid FIP header\\n\");\n+\t\treturn false;\n+\t}\n+\n+\treturn true;\n+}\n+\n+static int firmware_name_to_uuid(struct firmware *firmwarep,\n+\t\t\t\t struct uuid *uuid)\n+{\n+\tconst char *uuid_str = firmwarep->name;\n+\tint ret;\n+\n+\tret = uuid_str_to_bin(uuid_str, (unsigned char *)uuid,\n+\t\t\t      UUID_STR_FORMAT_STD);\n+\tif (ret)\n+\t\tlog_err(\"Invalid UUID str: %s\\n\", uuid_str);\n+\n+\treturn ret;\n+}\n+\n+static int check_fip_toc_entry(struct fip_toc_entry *ent,\n+\t\t\t       struct uuid *uuid,\n+\t\t\t       struct fip_toc_entry *dent)\n+{\n+\tstruct uuid uuid_null = { };\n+\n+\t/* NULL uuid. We parsed every entry */\n+\tif (!memcmp(&ent->uuid, &uuid_null, sizeof(uuid_null)))\n+\t\treturn -ENOENT;\n+\n+\t/* We found the related uuid */\n+\tif (!memcmp(&ent->uuid, uuid, sizeof(*uuid))) {\n+\t\tlog_debug(\"Found matching FIP entry. offset: 0x%llx size: %lld\\n\",\n+\t\t\t  ent->offset_address, ent->size);\n+\t\tmemcpy(dent, ent, sizeof(*ent));\n+\t\treturn 0;\n+\t}\n+\n+\treturn -EAGAIN;\n+}\n+\n+static int blk_read_fip_toc_header(struct blk_desc *desc, u32 offset,\n+\t\t\t\t   char *buf, struct fip_toc_header *hdr)\n+{\n+\tunsigned int blkcnt = BLOCK_CNT(sizeof(*hdr), desc);\n+\tunsigned long to_read;\n+\tsize_t read = 0;\n+\tint i, ret;\n+\n+\tfor (i = 0; i < blkcnt && read < sizeof(*hdr); i++) {\n+\t\tto_read = min(desc->blksz,\n+\t\t\t      (unsigned long)(sizeof(*hdr) - read));\n+\n+\t\tret = blk_dread(desc, offset + i, 1, buf);\n+\t\tif (ret != 1)\n+\t\t\treturn -EINVAL;\n+\n+\t\tmemcpy((u8 *)hdr + read, buf, to_read);\n+\t\tread += to_read;\n+\t}\n+\n+\treturn read;\n+}\n+\n+static int blk_read_fip_toc_entry(struct blk_desc *desc, u32 offset,\n+\t\t\t\t  int pos, char *buf,\n+\t\t\t\t  struct fip_toc_entry *ent)\n+{\n+\tunsigned long left, consumed, to_read, read = 0;\n+\tunsigned int blkstart, blkcnt;\n+\tint i, ret;\n+\n+\tconsumed = pos % desc->blksz;\n+\tleft = desc->blksz - consumed;\n+\tto_read = min(left, (unsigned long)sizeof(*ent));\n+\n+\tblkstart = BLOCK_CNT(pos, desc);\n+\tblkcnt = BLOCK_CNT(sizeof(*ent) - to_read, desc);\n+\n+\t/* Read data from previous cached block if present */\n+\tif (left) {\n+\t\tmemcpy(ent, buf + consumed, to_read);\n+\t\tread += to_read;\n+\t}\n+\n+\tfor (i = 0; i < blkcnt && read < sizeof(*ent); i++) {\n+\t\tto_read = min(desc->blksz,\n+\t\t\t      (unsigned long)(sizeof(*ent) - read));\n+\n+\t\tret = blk_dread(desc, offset + blkstart + i, 1, buf);\n+\t\tif (ret != 1)\n+\t\t\treturn -EINVAL;\n+\n+\t\tmemcpy((u8 *)ent + read, buf, to_read);\n+\t\tread += to_read;\n+\t}\n+\n+\treturn read;\n+}\n+\n+static int blk_parse_fip_firmware(struct firmware *firmwarep,\n+\t\t\t\t  struct blk_desc *desc,\n+\t\t\t\t  struct disk_partition *part_info,\n+\t\t\t\t  unsigned int part_offset,\n+\t\t\t\t  struct fip_toc_entry *dent)\n+{\n+\tunsigned int offset = part_info->start + part_offset;\n+\tstruct fip_toc_header hdr;\n+\tstruct fip_toc_entry ent;\n+\tstruct uuid uuid;\n+\tunsigned int pos;\n+\tchar *read_buf;\n+\tint ret;\n+\n+\t/* Allocate a Scratch Buffer for FIP parsing */\n+\tread_buf = malloc(desc->blksz);\n+\tif (!read_buf)\n+\t\treturn -ENOMEM;\n+\n+\tret = blk_read_fip_toc_header(desc, offset, read_buf, &hdr);\n+\tif (ret < 0) {\n+\t\tret = -EINVAL;\n+\t\tgoto out;\n+\t}\n+\n+\tpos = ret;\n+\n+\tif (!validate_fip_toc_header(&hdr)) {\n+\t\tret = -EINVAL;\n+\t\tgoto out;\n+\t}\n+\n+\tret = firmware_name_to_uuid(firmwarep, &uuid);\n+\tif (ret)\n+\t\tgoto out;\n+\n+\t/* Loop for every FIP entry searching for uuid */\n+\twhile (true) {\n+\t\tret = blk_read_fip_toc_entry(desc, offset, pos,\n+\t\t\t\t\t     read_buf, &ent);\n+\t\tif (ret < 0)\n+\t\t\tgoto out;\n+\n+\t\tpos += ret;\n+\n+\t\tret = check_fip_toc_entry(&ent, &uuid, dent);\n+\t\tif (ret != -EAGAIN)\n+\t\t\tbreak;\n+\t}\n+\n+out:\n+\tfree(read_buf);\n+\treturn ret;\n+}\n+\n+#ifdef CONFIG_CMD_UBIFS\n+static int ubi_parse_fip_firmware(struct firmware *firmwarep,\n+\t\t\t\t  char *ubi_vol,\n+\t\t\t\t  struct fip_toc_entry *dent)\n+{\n+\tstruct fip_toc_header hdr;\n+\tstruct fip_toc_entry ent;\n+\tstruct uuid uuid;\n+\tunsigned int pos;\n+\tint ret;\n+\n+\tret = ubi_volume_read(ubi_vol, (char *)&hdr, 0, sizeof(hdr));\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tpos = sizeof(hdr);\n+\n+\tif (!validate_fip_toc_header(&hdr))\n+\t\treturn -EINVAL;\n+\n+\tret = firmware_name_to_uuid(firmwarep, &uuid);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\t/* Loop for every FIP entry searching for uuid */\n+\twhile (true) {\n+\t\tret = ubi_volume_read(ubi_vol, (char *)&ent, pos,\n+\t\t\t\t      sizeof(ent));\n+\t\tif (ret)\n+\t\t\treturn ret;\n+\n+\t\tret = check_fip_toc_entry(&ent, &uuid, dent);\n+\t\tif (ret != -EAGAIN)\n+\t\t\tbreak;\n+\n+\t\tpos += sizeof(ent);\n+\t}\n+\n+\treturn ret;\n+}\n+#endif\n+\n+static int parse_fip_firmware(struct firmware *firmwarep,\n+\t\t\t      struct fip_storage_info *info,\n+\t\t\t      struct fip_toc_entry *dent)\n+{\n+\tswitch (info->storage_interface) {\n+\tcase FIP_STORAGE_INTERFACE_BLK:\n+\t\treturn blk_parse_fip_firmware(firmwarep, info->desc,\n+\t\t\t\t\t      &info->part_info,\n+\t\t\t\t\t      info->part_offset,\n+\t\t\t\t\t      dent);\n+#ifdef CONFIG_CMD_UBIFS\n+\tcase FIP_STORAGE_INTERFACE_UBI:\n+\t\treturn ubi_parse_fip_firmware(firmwarep,\n+\t\t\t\t\t      info->ubi_volume,\n+\t\t\t\t\t      dent);\n+#endif\n+\tdefault:\n+\t\treturn -EINVAL;\n+\t}\n+}\n+\n+static int blk_read_fip_firmware(struct firmware *firmwarep,\n+\t\t\t\t struct blk_desc *desc,\n+\t\t\t\t struct disk_partition *part_info,\n+\t\t\t\t unsigned int part_offset,\n+\t\t\t\t const struct fip_toc_entry *ent)\n+{\n+\tunsigned int offset = part_info->start + part_offset;\n+\tunsigned long pos, to_read, read = 0;\n+\tunsigned long long blkstart;\n+\tunsigned int blkcnt;\n+\tchar *read_buf;\n+\tsize_t size;\n+\tint i, ret;\n+\n+\tread_buf = malloc(desc->blksz);\n+\tif (!read_buf)\n+\t\treturn -ENOMEM;\n+\n+\tsize = ent->size - firmwarep->offset;\n+\tblkcnt = BLOCK_CNT(size, desc);\n+\tblkstart = ent->offset_address + firmwarep->offset;\n+\tpos = do_div(blkstart, desc->blksz);\n+\n+\t/* Read data in the middle of a block */\n+\tif (pos) {\n+\t\tto_read = min(desc->blksz - pos, (unsigned long)size);\n+\t\tret = blk_dread(desc, offset + blkstart, 1, read_buf);\n+\t\tif (ret != 1) {\n+\t\t\tret = -EINVAL;\n+\t\t\tgoto out;\n+\t\t}\n+\n+\t\tmemcpy((u8 *)firmwarep->data, read_buf + pos, to_read);\n+\t\tread += to_read;\n+\t\tblkstart++;\n+\t}\n+\n+\t/* Consume all the remaining block */\n+\tfor (i = 0; i < blkcnt && read < size; i++) {\n+\t\tto_read = min(desc->blksz, (unsigned long)(size - read));\n+\t\tret = blk_dread(desc, offset + blkstart + i, 1, read_buf);\n+\t\tif (ret != 1) {\n+\t\t\tret = -EINVAL;\n+\t\t\tgoto out;\n+\t\t}\n+\n+\t\tmemcpy((u8 *)firmwarep->data + read, read_buf, to_read);\n+\t\tread += to_read;\n+\t}\n+\n+\tret = read;\n+\n+out:\n+\tfree(read_buf);\n+\treturn ret;\n+}\n+\n+#ifdef CONFIG_CMD_UBIFS\n+static int ubi_read_fip_firmware(struct firmware *firmwarep,\n+\t\t\t\t char *ubi_vol,\n+\t\t\t\t const struct fip_toc_entry *ent)\n+{\n+\tunsigned int offset = firmwarep->offset;\n+\tsize_t size = ent->size;\n+\tint ret;\n+\n+\tret = ubi_volume_read(ubi_vol,\n+\t\t\t      (u8 *)firmwarep->data,\n+\t\t\t      ent->offset_address + offset,\n+\t\t\t      size - offset);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\treturn size - firmwarep->offset;\n+}\n+#endif\n+\n+static int read_fip_firmware(struct firmware *firmwarep,\n+\t\t\t     struct fip_storage_info *info,\n+\t\t\t     const struct fip_toc_entry *dent)\n+{\n+\tswitch (info->storage_interface) {\n+\tcase FIP_STORAGE_INTERFACE_BLK:\n+\t\treturn blk_read_fip_firmware(firmwarep, info->desc,\n+\t\t\t\t\t     &info->part_info,\n+\t\t\t\t\t     info->part_offset,\n+\t\t\t\t\t     dent);\n+#ifdef CONFIG_CMD_UBIFS\n+\tcase FIP_STORAGE_INTERFACE_UBI:\n+\t\treturn ubi_read_fip_firmware(firmwarep,\n+\t\t\t\t\t     info->ubi_volume,\n+\t\t\t\t\t     dent);\n+#endif\n+\tdefault:\n+\t\treturn -EINVAL;\n+\t}\n+}\n+\n+static int fw_parse_storage_info(struct udevice *dev,\n+\t\t\t\t struct fip_storage_info *info)\n+{\n+\tchar *storage_interface, *dev_part, *ubi_mtdpart, *ubi_volume;\n+\tstruct device_plat *plat = dev_get_uclass_plat(dev);\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+\tinfo->part_offset = env_get_hex(\"fw_partoffset\", 0);\n+\n+\tif (storage_interface && dev_part) {\n+\t\tint part;\n+\n+\t\tpart = part_get_info_by_dev_and_name_or_num(storage_interface,\n+\t\t\t\t\t\t\t    dev_part,\n+\t\t\t\t\t\t\t    &info->desc,\n+\t\t\t\t\t\t\t    &info->part_info, 1);\n+\t\tif (part < 0)\n+\t\t\treturn part;\n+\n+\t\tinfo->storage_interface = FIP_STORAGE_INTERFACE_BLK;\n+\n+\t\treturn 0;\n+\t}\n+\n+\tif (storage_interface && ubi_mtdpart && ubi_volume) {\n+\t\tif (strcmp(\"ubi\", storage_interface))\n+\t\t\treturn -ENODEV;\n+\n+\t\tret = generic_fw_loader_ubi_select(ubi_mtdpart);\n+\t\tif (ret)\n+\t\t\treturn ret;\n+\n+\t\tinfo->ubi_volume = ubi_volume;\n+\t\tinfo->storage_interface = FIP_STORAGE_INTERFACE_UBI;\n+\n+\t\treturn 0;\n+\t}\n+\n+\tinfo->part_offset = plat->partoffset;\n+\n+\tif (plat->phandlepart.phandle) {\n+\t\tstruct udevice *disk_dev;\n+\t\tofnode node;\n+\t\tint part;\n+\n+\t\tnode = ofnode_get_by_phandle(plat->phandlepart.phandle);\n+\n+\t\tret = device_get_global_by_ofnode(node, &disk_dev);\n+\t\tif (ret)\n+\t\t\treturn ret;\n+\n+\t\tinfo->desc = blk_get_by_device(disk_dev);\n+\t\tif (!info->desc)\n+\t\t\treturn -ENODEV;\n+\n+\t\tpart = plat->phandlepart.partition;\n+\t\tif (part >= 1)\n+\t\t\tret = part_get_info(info->desc, part,\n+\t\t\t\t\t    &info->part_info);\n+\t\telse\n+\t\t\tret = part_get_info_whole_disk(info->desc,\n+\t\t\t\t\t\t       &info->part_info);\n+\n+\t\tinfo->storage_interface = FIP_STORAGE_INTERFACE_BLK;\n+\n+\t\treturn ret;\n+\t}\n+\n+\tif (plat->mtdpart && plat->ubivol) {\n+\t\tret = generic_fw_loader_ubi_select(plat->mtdpart);\n+\t\tif (ret)\n+\t\t\treturn ret;\n+\n+\t\tinfo->ubi_volume = plat->ubivol;\n+\t\tinfo->storage_interface = FIP_STORAGE_INTERFACE_UBI;\n+\n+\t\treturn 0;\n+\t}\n+\n+\treturn -EINVAL;\n+}\n+\n+/**\n+ * fw_get_fip_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_fip_firmware(struct udevice *dev)\n+{\n+\tstruct fip_storage_info info = { };\n+\tstruct firmware *firmwarep;\n+\tstruct fip_toc_entry ent;\n+\tint ret;\n+\n+\tret = fw_parse_storage_info(dev, &info);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tfirmwarep = dev_get_uclass_priv(dev);\n+\tif (!firmwarep)\n+\t\treturn -EINVAL;\n+\n+\tret = parse_fip_firmware(firmwarep, &info, &ent);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tif (ent.size - firmwarep->offset > firmwarep->size) {\n+\t\tlog_err(\"Not enough space to read firmware\\n\");\n+\t\treturn -ENOMEM;\n+\t}\n+\n+\tret = read_fip_firmware(firmwarep, &info, &ent);\n+\tif (ret < 0)\n+\t\tlog_err(\"Failed to read %s from FIP: %d.\\n\",\n+\t\t\tfirmwarep->name, ret);\n+\n+\treturn ret;\n+}\n+\n+/**\n+ * fw_get_fip_firmware_size - get firmware size.\n+ * @dev: An instance of a driver.\n+ *\n+ * Return: Size of firmware, negative value when error.\n+ */\n+static int fw_get_fip_firmware_size(struct udevice *dev)\n+{\n+\tstruct fip_storage_info info = { };\n+\tstruct firmware *firmwarep;\n+\tstruct fip_toc_entry ent;\n+\tint ret;\n+\n+\tret = fw_parse_storage_info(dev, &info);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tfirmwarep = dev_get_uclass_priv(dev);\n+\tif (!firmwarep)\n+\t\treturn -EINVAL;\n+\n+\tret = parse_fip_firmware(firmwarep, &info, &ent);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\treturn ent.size;\n+}\n+\n+static const struct fw_loader_ops fip_loader_ops = {\n+\t.get_firmware = fw_get_fip_firmware,\n+\t.get_size = fw_get_fip_firmware_size,\n+};\n+\n+static const struct udevice_id fip_loader_ids[] = {\n+\t{ .compatible = \"u-boot,fip-loader\"},\n+\t{ }\n+};\n+\n+U_BOOT_DRIVER(fip_loader) = {\n+\t.name\t\t= \"fip-loader\",\n+\t.id\t\t= UCLASS_FIRMWARE_LOADER,\n+\t.of_match\t= fip_loader_ids,\n+\t.ops\t\t= &fip_loader_ops,\n+};\ndiff --git a/drivers/misc/fw_loader/fw_loader-uclass.c b/drivers/misc/fw_loader/fw_loader-uclass.c\nindex 19379c23411b..1d47c4437072 100644\n--- a/drivers/misc/fw_loader/fw_loader-uclass.c\n+++ b/drivers/misc/fw_loader/fw_loader-uclass.c\n@@ -62,6 +62,9 @@ static int fw_loader_pre_probe(struct udevice *dev)\n \n \t\tplat->ubivol = (char *)ofnode_read_string(fw_loader_node,\n \t\t\t\t\t\t\t  \"ubivol\");\n+\n+\t\tofnode_read_u32(fw_loader_node, \"partoffset\",\n+\t\t\t\t&plat->partoffset);\n \t}\n \n \tif (plat->phandlepart.phandle) {\ndiff --git a/drivers/misc/fw_loader/internal.h b/drivers/misc/fw_loader/internal.h\nindex 9964dc436afb..6003b15ab9ac 100644\n--- a/drivers/misc/fw_loader/internal.h\n+++ b/drivers/misc/fw_loader/internal.h\n@@ -49,11 +49,13 @@ struct fw_loader_ops {\n  * This holds information about all supported storage devices for driver use.\n  *\n  * @phandlepart: Attribute data for block device.\n+ * @partoffset: Global offset for BLK partition.\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+\tu32 partoffset;\n \tchar *mtdpart;\n \tchar *ubivol;\n };\n",
    "prefixes": [
        "v6",
        "5/6"
    ]
}