{"id":2233068,"url":"http://patchwork.ozlabs.org/api/1.2/patches/2233068/?format=json","web_url":"http://patchwork.ozlabs.org/project/uboot/patch/20260505-b4-qcom-tooling-improvements-v6-3-a5fb673f4af6@linaro.org/","project":{"id":18,"url":"http://patchwork.ozlabs.org/api/1.2/projects/18/?format=json","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":"<20260505-b4-qcom-tooling-improvements-v6-3-a5fb673f4af6@linaro.org>","list_archive_url":null,"date":"2026-05-05T15:48:43","name":"[v6,3/6] tools: qcom: add mkmbn.py","commit_ref":null,"pull_url":null,"state":"new","archived":false,"hash":"6e245b335de88575abaf57016846a124f915ef5d","submitter":{"id":90679,"url":"http://patchwork.ozlabs.org/api/1.2/people/90679/?format=json","name":"Casey Connolly","email":"casey.connolly@linaro.org"},"delegate":{"id":151538,"url":"http://patchwork.ozlabs.org/api/1.2/users/151538/?format=json","username":"kcxt","first_name":"Casey","last_name":"Connolly","email":"casey.connolly@linaro.org"},"mbox":"http://patchwork.ozlabs.org/project/uboot/patch/20260505-b4-qcom-tooling-improvements-v6-3-a5fb673f4af6@linaro.org/mbox/","series":[{"id":502858,"url":"http://patchwork.ozlabs.org/api/1.2/series/502858/?format=json","web_url":"http://patchwork.ozlabs.org/project/uboot/list/?series=502858","date":"2026-05-05T15:48:40","name":"Qualcomm: teach the build system to emit signed ELF images","version":6,"mbox":"http://patchwork.ozlabs.org/series/502858/mbox/"}],"comments":"http://patchwork.ozlabs.org/api/patches/2233068/comments/","check":"pending","checks":"http://patchwork.ozlabs.org/api/patches/2233068/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=linaro.org header.i=@linaro.org header.a=rsa-sha256\n header.s=google header.b=lNYJSkZZ;\n\tdkim-atps=neutral","legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de\n (client-ip=85.214.62.61; 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=linaro.org","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=linaro.org header.i=@linaro.org header.b=\"lNYJSkZZ\";\n\tdkim-atps=neutral","phobos.denx.de;\n dmarc=pass (p=none dis=none) header.from=linaro.org","phobos.denx.de;\n spf=pass smtp.mailfrom=casey.connolly@linaro.org"],"Received":["from phobos.denx.de (phobos.denx.de [85.214.62.61])\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 4g92xs1Vrvz1yJx\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 06 May 2026 01:49:21 +1000 (AEST)","from h2850616.stratoserver.net (localhost [IPv6:::1])\n\tby phobos.denx.de (Postfix) with ESMTP id 81D218498E;\n\tTue,  5 May 2026 17:48:56 +0200 (CEST)","by phobos.denx.de (Postfix, from userid 109)\n id 34FDB8495E; Tue,  5 May 2026 17:48:55 +0200 (CEST)","from mail-wm1-x32d.google.com (mail-wm1-x32d.google.com\n [IPv6:2a00:1450:4864:20::32d])\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 A3CCA848B7\n for <u-boot@lists.denx.de>; Tue,  5 May 2026 17:48:52 +0200 (CEST)","by mail-wm1-x32d.google.com with SMTP id\n 5b1f17b1804b1-48a563e4ef7so52485115e9.0\n for <u-boot@lists.denx.de>; Tue, 05 May 2026 08:48:52 -0700 (PDT)","from lion.localdomain (p4fc3dd86.dip0.t-ipconnect.de.\n [79.195.221.134]) by smtp.gmail.com with ESMTPSA id\n 5b1f17b1804b1-48d182ee923sm20305955e9.27.2026.05.05.08.48.50\n (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n Tue, 05 May 2026 08:48:51 -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,RCVD_IN_DNSWL_BLOCKED,\n SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.2","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=linaro.org; s=google; t=1777996132; x=1778600932; darn=lists.denx.de;\n h=cc:to:in-reply-to:references:message-id:content-transfer-encoding\n :mime-version:subject:date:from:from:to:cc:subject:date:message-id\n :reply-to; bh=JiTbv1ntNw0zBwBGG4FYd+0LUISH9umlDgcxhuUZK7Q=;\n b=lNYJSkZZ6GK1Er2ParO2rkLOI9Oz/a60kkuhGBd+u2AasbGBgpEIefozQEQZ1O6cFg\n 690Y1kGFAJOCYjDStXSG3lyyFDXaj9vmKZT5nK55gfz5duXl15Q5IpSx/t0Y6LqzPp42\n kLeyOG/Wu25UUmhSIxeTTzJZ1j/0hROtfgny8h+2cb/RwpGIy1feHI8f+Lq5iKuUTUSW\n K0T8cIOORVHnWGTSqGBCUGz4BTSWKLsZfO+aKFw2Ef+4SdkoZt7mf3PL7GjlhsB0rfvX\n Y2OoWeQuqP2ls+DsNk3YKfx21H8eqdDql+Bac+IsxWUwRWGuWNyk//eiPmbnL8qqIciL\n 78BQ==","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20251104; t=1777996132; x=1778600932;\n h=cc:to:in-reply-to:references:message-id:content-transfer-encoding\n :mime-version:subject:date:from:x-gm-gg:x-gm-message-state:from:to\n :cc:subject:date:message-id:reply-to;\n bh=JiTbv1ntNw0zBwBGG4FYd+0LUISH9umlDgcxhuUZK7Q=;\n b=rtCEGftQ/0d4/rq77DTWMPsmfoABPjOsn5FC3JPDzGzpL5VwsdL7FuKCB5ZQrsUN2p\n 6aSKJkO7Ox99O5J7WDvmpM1c0m5WynOSyRVI25WjwZDBiKGeRKHqmeG5aGE26+H4J2mu\n 0CPIbCxylmaPakBrpwQzA8kKRJKncRVnF8dzHSgw5fpnzaFohSljHvGTyJfz0ByITWZY\n n/XgCOJ0FuyFh+BQTwxfPgyggmvdr6wAyEzx/hGxa+3CTQZ3yp/ocWcS2CnV65TEEcyd\n Tg0ePSGGlHpBiEibjzgZv+IPW/BaFqZcJCtBw36zZy+9lfdp0RR2PKO4x+5MSCKTFMQD\n gesw==","X-Gm-Message-State":"AOJu0YxGyOl7B/CW6UPzbIYHDaeyI8CeqEqK4yq1ad1qs8Zdpz9bjWmE\n aPvtefKliVmzNxdGMv0tS3kcV06HwNySGIfG6v3rojZhU8ULdYtWcCiTKVQAh6fibN8=","X-Gm-Gg":"AeBDieulWdD6MbLHlzX4Uw92PCsQQiZYs6/dvzLJydW/lQLQYxemPzfQzSwSJkxIusP\n R56DtHT9Q4dNSRjPzM3vjZfJRHbjN7d1wQrNINPkfrmwOA+G/pEr3Wv950qU9EqouN3DR2Oyj6Y\n TJVhHdebxGCieRescT46nmtOwDwWB/7mhMeDGY00CCpYVDDfv/YXNLsmqa0l50dtGJr+QP3nV9H\n hDPHGlRFOEEZ/ZA4U2wAiK8yfhvAGJOogqZTE5F4ZUxWXOtqmiyremQaXab+zexMJKnE1IBNUue\n u+q4nYxGJPAoYWpPyqYG+pNaI/uVgI8cTfX5CHyBuIXEmEPmPRzRmsAi4xMyqIC5/+LZkEPd4EF\n OyOl3k6FhNxHsk1y/+aOO8uxFoQaAkFRVKA8N6OXzejuvBS9O9SHPW/EIng8N5CsWY+GAZj7rg9\n mmLmywwRK0D+t7W31BjrasUG9ibBssbLqXL008hj9LJQ7bcJrWcAr0Mfg8BWJzCQdODLLSxVBxQ\n CXVaLau9ygqBOHJMQ==","X-Received":"by 2002:a05:600c:a111:b0:486:fd5c:2b35 with SMTP id\n 5b1f17b1804b1-48d18bdc581mr45100045e9.13.1777996132123;\n Tue, 05 May 2026 08:48:52 -0700 (PDT)","From":"Casey Connolly <casey.connolly@linaro.org>","Date":"Tue, 05 May 2026 17:48:43 +0200","Subject":"[PATCH v6 3/6] tools: qcom: add mkmbn.py","MIME-Version":"1.0","Content-Type":"text/plain; charset=\"utf-8\"","Content-Transfer-Encoding":"7bit","Message-Id":"\n <20260505-b4-qcom-tooling-improvements-v6-3-a5fb673f4af6@linaro.org>","References":"\n <20260505-b4-qcom-tooling-improvements-v6-0-a5fb673f4af6@linaro.org>","In-Reply-To":"\n <20260505-b4-qcom-tooling-improvements-v6-0-a5fb673f4af6@linaro.org>","To":"u-boot@lists.denx.de, Sumit Garg <sumit.garg@kernel.org>,\n u-boot-qcom@groups.io","Cc":"Tom Rini <trini@konsulko.com>,\n Casey Connolly <casey.connolly@linaro.org>,\n Neil Armstrong <neil.armstrong@linaro.org>,\n Balaji Selvanathan <balaji.selvanathan@oss.qualcomm.com>,\n Varadarajan Narayanan <quic_varada@quicinc.com>,\n Quentin Schulz <quentin.schulz@cherry.de>,\n Heinrich Schuchardt <xypron.glpk@gmx.de>,\n Marek Vasut <marek.vasut+renesas@mailbox.org>, Peng Fan <peng.fan@nxp.com>,\n Jaehoon Chung <jh80.chung@samsung.com>,\n Aswin Murugan <aswin.murugan@oss.qualcomm.com>,\n Ilias Apalodimas <ilias.apalodimas@linaro.org>,\n Michal Simek <michal.simek@amd.com>, David Lechner <dlechner@baylibre.com>","X-Mailer":"b4 0.16-dev","X-Developer-Signature":"v=1; a=openpgp-sha256; l=8765;\n i=casey.connolly@linaro.org; h=from:subject:message-id;\n bh=qCCeU0T4p3Hzlzl8XWJ8BchZ+6/KH/zL9+4V1EWTcOk=;\n b=owGbwMvMwCFYaeA6f6eBkTjjabUkhsxfgrFTnUuWP4v7sLb9lGm++uNJ0yMy5Lab8XPFeH0LY\n 5q75MqGjlIWBkEOBlkxRRbxE8ssm9ZettfYvuACzBxWJpAhDFycAjCRHYqMDPPylAxSnWWZPa68\n mM6c8a2GS7Vs6va1D/ccZn+ZPu13ui8jw+QPjYJZSqa8rsxFUm9YOYOPpvOGnjFlu6f58OrWNqP\n VFwE=","X-Developer-Key":"i=casey.connolly@linaro.org; a=openpgp;\n fpr=83B24DA7FE145076BC38BB250CD904EB673A7C47","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":"Adjust the elf class to support creating ELF files from scratch so that\nmkmbn can build an MBN file from the U-Boot binary image and fix some\nimports to work correctly in the U-Boot build system.\n\nThe new tool inspects the DTB embedded in u-boot.bin and uses a lookup\ntable to determine the appropriate configuration based on the root\ncompatible property, effectively encoding the info that was previously\nkept in documentation.\n\nSigned-off-by: Casey Connolly <casey.connolly@linaro.org>\n---\n tools/mkmbn                 |   1 +\n tools/qcom/mkmbn/elf.py     |  36 ++++++++++\n tools/qcom/mkmbn/hashseg.py |   4 +-\n tools/qcom/mkmbn/mkmbn.py   | 165 ++++++++++++++++++++++++++++++++++++++++++++\n 4 files changed, 204 insertions(+), 2 deletions(-)","diff":"diff --git a/tools/mkmbn b/tools/mkmbn\nnew file mode 120000\nindex 000000000000..a7b2096756f7\n--- /dev/null\n+++ b/tools/mkmbn\n@@ -0,0 +1 @@\n+qcom/mkmbn/mkmbn.py\n\\ No newline at end of file\ndiff --git a/tools/qcom/mkmbn/elf.py b/tools/qcom/mkmbn/elf.py\nindex a5c4dad5ee01..4bd54239fbbe 100644\n--- a/tools/qcom/mkmbn/elf.py\n+++ b/tools/qcom/mkmbn/elf.py\n@@ -44,8 +44,24 @@ class Ehdr:\n \n \tCLASS32 = 1\n \tCLASS64 = 2\n \n+\t# Init a qcom XBL style ELF header\n+\tdef __init__(self):\n+\t\tself.ei_magic = b\"\\x7fELF\"\n+\t\tself.ei_class = 2\n+\t\tself.ei_data = 1\n+\t\tself.ei_version = 1\n+\t\tself.ei_os_abi = 0\n+\t\tself.ei_abi_version = 0\n+\t\tself.e_type = 2\n+\t\tself.e_machine = 183\n+\t\tself.e_version = 1\n+\n+\t\tself.e_ehsize = 64\n+\t\tself.e_phoff = 64\n+\t\tself.e_phentsize = 56\n+\n \t@staticmethod\n \tdef parse(b: bytes) -> Ehdr:\n \t\thdr_unpack = Ehdr.START_FORMAT.unpack_from(b)\n \t\thdr = Ehdr(*hdr_unpack)\n@@ -109,8 +125,24 @@ class Phdr:\n \t\t\tunpack.insert(-1, flags)\n \n \t\treturn Phdr(*unpack)\n \n+\t@staticmethod\n+\tdef from_bin(b: bytes, loadaddr: int) -> Phdr:\n+\t\t# p_offset is fixed later\n+\t\tphdr = Phdr(\n+\t\t\tp_type=1,\n+\t\t\tp_offset=0xFFFFFFFF,\n+\t\t\tp_vaddr=loadaddr,\n+\t\t\tp_paddr=loadaddr,\n+\t\t\tp_filesz=len(b),\n+\t\t\tp_memsz=len(b),\n+\t\t\tp_flags=7,\n+\t\t\tp_align=0x1000,\n+\t\t)\n+\t\tphdr.data = memoryview(b)\n+\t\treturn phdr\n+\n \tdef save(self, f: BinaryIO, ei_class: int) -> int:\n \t\tunpack = dataclasses.astuple(self)\n \n \t\tif ei_class == Ehdr.CLASS32:\n@@ -142,8 +174,12 @@ def align(i: int, alignment: int) -> int:\n class Elf:\n \tehdr: Ehdr\n \tphdrs: List[Phdr]\n \n+\tdef __init__(self):\n+\t\tself.ehdr = Ehdr()\n+\t\tself.phdrs: List[Phdr] = []\n+\n \tdef total_header_size(self):\n \t\treturn self.ehdr.e_phoff + len(self.phdrs) * self.ehdr.e_phentsize\n \n \t@staticmethod\ndiff --git a/tools/qcom/mkmbn/hashseg.py b/tools/qcom/mkmbn/hashseg.py\nindex fe74761ae8df..db157a23d186 100644\n--- a/tools/qcom/mkmbn/hashseg.py\n+++ b/tools/qcom/mkmbn/hashseg.py\n@@ -14,10 +14,10 @@ import hashlib\n from dataclasses import dataclass\n from io import BytesIO\n from struct import Struct\n \n-from . import cert\n-from . import elf\n+import cert\n+import elf\n \n # A typical Qualcomm firmware might have the following program headers:\n #     LOAD off    0x00000800 vaddr 0x86400000 paddr 0x86400000 align 2**11\n #          filesz 0x00001000 memsz 0x00001000 flags rwx\ndiff --git a/tools/qcom/mkmbn/mkmbn.py b/tools/qcom/mkmbn/mkmbn.py\nnew file mode 100755\nindex 000000000000..e4484b539b02\n--- /dev/null\n+++ b/tools/qcom/mkmbn/mkmbn.py\n@@ -0,0 +1,165 @@\n+#!/usr/bin/env python3\n+# SPDX-License-Identifier: GPL-2.0-only\n+# Copyright (C) 2024 Stephan Gerhold\n+# Copyright (C) 2026 Casey Connolly\n+#\n+# This is a port of qtestsign designed to integrate with the\n+# U-Boot build system. See the qtestsign repo for more information.\n+# https://github.com/msm8916-mainline/qtestsign\n+#\n+from __future__ import annotations\n+\n+import argparse\n+from pathlib import Path\n+\n+from elf import Elf, Phdr\n+import hashseg\n+import sys\n+from enum import Enum\n+import struct\n+\n+verbose = False\n+\n+def log(*args, **kwargs):\n+    if verbose:\n+        print(*args, *kwargs, file=sys.stderr)\n+\n+def error(*args, **kwargs):\n+    print(\"mkmbn: \", file=sys.stderr, end='')\n+    print(*args, *kwargs, file=sys.stderr)\n+\n+class SwId(Enum):\n+    sbl1 = 0x00\n+    mba = 0x01\n+    modem = 0x02\n+    prog = 0x03\n+    adsp = 0x04\n+    devcfg = 0x05\n+    tz = 0x07\n+    aboot = 0x09\n+    uefi = 0x09\n+    rpm = 0x0A\n+    tz_app = 0x0C\n+    wcnss = 0x0D\n+    venus = 0x0E\n+    wlanmdsp = 0x12\n+    gpu = 0x14\n+    hyp = 0x15\n+    cdsp = 0x17\n+    slpi = 0x18\n+    abl = 0x1C\n+    cmnlib = 0x1F\n+    aop = 0x21\n+    qup = 0x24\n+    xbl_config = 0x25\n+\n+class MbnData:\n+\n+    # sw_id 0x9 is aboot/uefi, the most common\n+    def __init__(self, loadaddr: int, version: int, sw_id: SwId = SwId.aboot):\n+        self.loadaddr = loadaddr\n+        self.version = version\n+        self.sw_id = sw_id\n+\n+\n+\"\"\"\n+This dictionary is used to map a board or platform to the appropriate load address and\n+other MBN metadata. When adding support for a new platform to U-Boot, the appropriate\n+data should be filled out here. The load address can typically be determined by looking\n+at the uefi.elf or xbl.elf for the platform. For the uefi.elf it is the load address, and\n+for xbl.elf it is typically the RWX section in the middle, just BEFORE the section loaded\n+at 0x1495xxxx or similar. Looking at similar platforms in the table below may help.\n+\"\"\"\n+boards: dict[bytes, MbnData] = {\n+    # Exact matches for boards, these are preferred\n+    b\"qcom,qcs6490-rb3gen2\\0\": MbnData(0x9FC00000, 6, SwId.uefi),\n+    b\"qcom,qcs9100-ride-r3\\0\": MbnData(0xAF000000, 6, SwId.uefi),  # Dragonwing IQ9\n+    b\"qcom,qcs8300-ride\\0\": MbnData(0xAF000000, 6, SwId.uefi),  # Dragonwing IQ8\n+    b\"qcom,qcs615-ride\\0\": MbnData(0x9FC00000, 6, SwId.uefi),  # Dragonwing IQ6\n+    # Fallback/generic matches since most boards for a platform will\n+    # use the same load address\n+    b\"qcom,qcm6490\\0\": MbnData(0x9FC00000, 6, SwId.uefi),  # rb3gen2, rubikpi3\n+    b\"qcom,qcs9100\\0\": MbnData(0xAF000000, 6, SwId.uefi),  # Dragonwing IQ9\n+    b\"qcom,qcs8300\\0\": MbnData(0xAF000000, 6, SwId.uefi),  # Dragonwing IQ8\n+    b\"qcom,qcs8550\\0\": MbnData(0xA7000000, 7, SwId.uefi),  # C8550\n+    b\"qcom,sm8550\\0\": MbnData(0xA7000000, 7, SwId.uefi),  # C8550\n+    b\"qcom,sm8650\\0\": MbnData(0xA7000000, 7, SwId.uefi),  # SM8650\n+    b\"qcom,qcs615\\0\": MbnData(0x9FC00000, 6, SwId.uefi),  # Dragonwing IQ6\n+    b\"qcom,ipq5424\\0\": MbnData(0x8a380000, 6, SwId.aboot),\n+    b\"qcom,ipq9574\\0\": MbnData(0x4A240000, 6, SwId.aboot),\n+\n+    # msm8916/apq8016 has an \"aboot\" partition but the process is the same\n+    # They use header version 3.\n+    b\"qcom,apq8016\\0\": MbnData(0x8f600000, 3, SwId.aboot),\n+    b\"qcom,msm8916\\0\": MbnData(0x8f600000, 3, SwId.aboot),\n+}\n+\n+parser = argparse.ArgumentParser(\n+    description=\"\"\"\n+\tCreate a signed Qualcomm \"uefi\" ELF image\n+\"\"\"\n+)\n+parser.register(\"type\", \"hex\", lambda s: int(s, 16))\n+parser.add_argument(\n+    \"-o\", \"--output\", type=Path, default=\"u-boot.mbn\", help=\"Output file\"\n+)\n+parser.add_argument(\n+    \"-v\", dest=\"verbose\", action=\"store_true\", default=False, help=\"Verbose\"\n+)\n+parser.add_argument(\n+    \"bin\", type=argparse.FileType(\"rb\"), help=\"Binary to embed (e.g. u-boot.bin)\"\n+)\n+args = parser.parse_args()\n+verbose = args.verbose\n+\n+elf = Elf()\n+\n+data: bytes = args.bin.read()\n+\n+# dtb is at the end, so find the last match\n+dtb_off = 0\n+off = 0\n+dtb_size = 0\n+while True:\n+    off = data.find(b\"\\xd0\\x0d\\xfe\\xed\", dtb_off + dtb_size)\n+    if off == -1:\n+        break\n+    (dtb_size,) = struct.unpack_from(\"I\", data, offset=off)\n+    dtb_off = off\n+\n+if not dtb_off:\n+    print(\"Couldn't find DTB in provided binary!\")\n+    exit(1)\n+\n+log(f\"Found FDT at {dtb_off:#x} size {dtb_size:#x}\")\n+\n+mbn: MbnData|None = None\n+\n+for match, mbndata in boards.items():\n+    if data.find(match, dtb_off) != -1:\n+        mbn = mbndata\n+        break\n+\n+if not mbn:\n+    error(\n+        \"CONFIG_QCOM_GENERATE_MBN is enabled but this platform doesn't appear to be supported\\n\"\n+        \"Please see tools/qcom/mkmbn/mkmbn.py for details. If you intend to chainload U-Boot\\n\"\n+        \"then disregard this message and disable CONFIG_QCOM_GENERATE_MBN in your defconfig.\"\n+    )\n+    args.output.unlink(missing_ok=True)\n+    exit(1)\n+\n+log(f\"Detected board {match.decode('UTF-8')} with load address {mbn.loadaddr:#x}\")\n+\n+elf.phdrs.append(Phdr.from_bin(data, mbn.loadaddr))\n+elf.ehdr.e_entry = mbn.loadaddr\n+elf.update()\n+\n+# QLI boards use v6 sw_id is \"aboot\"\n+hashseg.generate(elf, mbn.version, mbn.sw_id.value)\n+# print(f\"after: {elf}\")\n+\n+with open(args.output, \"wb\") as f:\n+    elf.save(f)\n+\n+log(f\"Built signed MBN: {args.output.resolve()}\")\n","prefixes":["v6","3/6"]}