From nobody Wed Jun 24 04:48:19 2026 X-Original-To: dev-commits-src-main@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4glTw86rHmz6hc1t for ; Wed, 24 Jun 2026 04:48:24 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "YR1" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4glTw84YD3z4Ltx for ; Wed, 24 Jun 2026 04:48:24 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1782276504; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=NYgPA9tnn1AO5DLhVZ+JYCqMsQ2yIbMSM03tkXqvmiY=; b=jr6MojcD8tkFbb8qeIo4p++uwiUVM1PI/XusNOUITTgRRzCwIO9Qvazrype+u2WkkxKAP9 qN4bOJ9GRiNxGvhAfcBFo0dHpL3ngm2V3NFdCNmSMErDtqVD4sCADYKTUG3EudIFbdR/v8 atIuVFVK3N5Ex+/pqIYS9nA7IbbzFCRxi1uDlij7hdgAc4pD2F5cycTYLwUyobI5zVxthj FIsBfD76QEDu52Lo+X/YDOjY/r8DwOryIv1G9MrPdEVGoqJxxRPUTX1yknTiyOgM5BFK78 Kw0Qs+rm9XlgGW3VE/uEzVNARLCqFrO3dv5SYZqHpGkAXA/GmEp6qumA4BugTw== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1782276504; a=rsa-sha256; cv=none; b=MnnHhk6iEd7+O5YTIm8poGxtJcZgDGFbmMkGBZ86LPFje3zwAFfEW6XWEYCbS7DRL6iKmw CGev4X9RjQ0GWa6v/OK8J3y/kWm2KFbZSeML7Tx7pCc2mrs8oE1z/uQp9izUo2aG++B8pg v730vY9MLH2pa6MKVxekEcUwquq9sY1hc6tMod9eCYhOVuwSU/LmLMcLobV1fGCzCSVcfI FnexZOWyoPXYzmm+JmOVTQPWhs/ctHv6DfTmZlPWRSQVwfUsiDRms4qqhgh5CUHipAOyUZ Ao0Rym3WedF4RTfm2Lw6L+ZZD90aT+uMWITwgBIwwRqU4heDDosQ3nssOB68AQ== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1782276504; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=NYgPA9tnn1AO5DLhVZ+JYCqMsQ2yIbMSM03tkXqvmiY=; b=WzSp9fyTJM2UUoOnYtrJXdqNIX3HoDmtlUcgzbQIE8+Ccg3deLp+fXrtEaT/ZAhxboWa4M uYbp1pfTe6s0NyXzJr5Dtl7qD2FKHN21nOzzavbelNm4xys7OOIy18hzPQM4LcRJ+Zo0n5 vCHzd3ymOtdqYPfEAjpEnG+NlIyOvw1VUylPa1GfZkMa/VwP8xjAcetnlXwtT3DBcg7y29 m4T6nNPW+2iKkOAhFFSkNNocfKjPiYjS+VkxDRtB5eurCdTG9Cn+9LUgs+P6ZJRQfGYhL5 D/ETz1jMgxjdPG+L0QQOowZlX79/kRn2aAmM9pU3kTFjHFaf0PzJsSC+ZmKYnQ== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4glTw83Cgkz14rD for ; Wed, 24 Jun 2026 04:48:24 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 25495 by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Wed, 24 Jun 2026 04:48:19 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org Cc: Christos Longros From: Warner Losh Subject: git: 9417b115a283 - main - loader/efi: pre-allocate memory map buffer before ExitBootServices List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-main@freebsd.org Sender: owner-dev-commits-src-main@FreeBSD.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: imp X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 9417b115a283f4c09da35c5ccff9787e2ac95505 Auto-Submitted: auto-generated Date: Wed, 24 Jun 2026 04:48:19 +0000 Message-Id: <6a3b6193.25495.456860ff@gitrepo.freebsd.org> The branch main has been updated by imp: URL: https://cgit.FreeBSD.org/src/commit/?id=9417b115a283f4c09da35c5ccff9787e2ac95505 commit 9417b115a283f4c09da35c5ccff9787e2ac95505 Author: Christos Longros AuthorDate: 2026-06-24 04:42:12 +0000 Commit: Warner Losh CommitDate: 2026-06-24 04:46:16 +0000 loader/efi: pre-allocate memory map buffer before ExitBootServices Move the memory map allocation before the ExitBootServices retry loop to ensure no boot service calls occur between GetMemoryMap and ExitBootServices. This simplifies the control flow by removing the inner sizing loop and matches the strategy used by the Linux EFI stub. Identified while investigating an ExitBootServices hang on AMD AGESA 1.3.0.0a firmware (Gigabyte B650 GAMING X AX V2). Signed-off-by: Christos Longros Reviewed by: imp Differential Revision: https://reviews.freebsd.org/D56249 --- stand/efi/loader/bootinfo.c | 85 ++++++++++++++++++++++++--------------------- 1 file changed, 46 insertions(+), 39 deletions(-) diff --git a/stand/efi/loader/bootinfo.c b/stand/efi/loader/bootinfo.c index 14e16ed5df81..221c1dfdc56f 100644 --- a/stand/efi/loader/bootinfo.c +++ b/stand/efi/loader/bootinfo.c @@ -242,52 +242,59 @@ bi_load_efi_data(struct preloaded_file *kfp, bool exit_bs) * the memory map are caused by splitting a range of free * memory into two, so that one is marked as being loader * data. + * + * Perform the allocation before the ExitBootServices retry + * loop so that no boot service calls (AllocatePages, + * FreePages) are made between GetMemoryMap and + * ExitBootServices. The UEFI specification (s7.4.6) requires + * that the memory map key passed to ExitBootServices match + * the current map; calling any boot service in between may + * invalidate the key. This matches the pre-allocation + * strategy used by the Linux EFI stub. */ - sz = 0; - mm = NULL; + status = BS->GetMemoryMap(&sz, NULL, &efi_mapkey, &dsz, &mmver); + if (status != EFI_BUFFER_TOO_SMALL) { + printf("%s: GetMemoryMap error %lu\n", __func__, + DECODE_ERROR(status)); + return (EINVAL); + } + sz += (10 * dsz); + pages = EFI_SIZE_TO_PAGES(sz + efisz); + status = BS->AllocatePages(AllocateAnyPages, EfiLoaderData, + pages, &addr); + if (EFI_ERROR(status)) { + printf("%s: AllocatePages error %lu\n", __func__, + DECODE_ERROR(status)); + return (ENOMEM); + } + + /* + * Read the memory map and stash it after bootinfo. Align the + * memory map on a 16-byte boundary (the bootinfo block is page + * aligned). + */ + efihdr = (struct efi_map_header *)(uintptr_t)addr; + mm = (void *)((uint8_t *)efihdr + efisz); /* * Matthew Garrett has observed at least one system changing the - * memory map when calling ExitBootServices, causing it to return an - * error, probably because callbacks are allocating memory. - * So we need to retry calling it at least once. + * memory map when calling ExitBootServices, causing it to return + * an error, probably because EBS event handlers allocate memory. + * + * The retry loop must not call any boot services between + * GetMemoryMap and ExitBootServices. Any boot service call + * (including printf/OutputString) can invalidate the memory + * map key, and the spec requires the key to be current. */ for (retry = 2; retry > 0; retry--) { - for (;;) { - status = BS->GetMemoryMap(&sz, mm, &efi_mapkey, &dsz, &mmver); - if (!EFI_ERROR(status)) - break; - - if (status != EFI_BUFFER_TOO_SMALL) { - printf("%s: GetMemoryMap error %lu\n", __func__, - DECODE_ERROR(status)); - return (EINVAL); - } - - if (addr != 0) - BS->FreePages(addr, pages); - - /* Add 10 descriptors to the size to allow for - * fragmentation caused by calling AllocatePages */ - sz += (10 * dsz); - pages = EFI_SIZE_TO_PAGES(sz + efisz); - status = BS->AllocatePages(AllocateAnyPages, EfiLoaderData, - pages, &addr); - if (EFI_ERROR(status)) { - printf("%s: AllocatePages error %lu\n", __func__, - DECODE_ERROR(status)); - return (ENOMEM); - } - - /* - * Read the memory map and stash it after bootinfo. Align the - * memory map on a 16-byte boundary (the bootinfo block is page - * aligned). - */ - efihdr = (struct efi_map_header *)(uintptr_t)addr; - mm = (void *)((uint8_t *)efihdr + efisz); - sz = (EFI_PAGE_SIZE * pages) - efisz; + sz = (EFI_PAGE_SIZE * pages) - efisz; + status = BS->GetMemoryMap(&sz, mm, &efi_mapkey, &dsz, &mmver); + if (EFI_ERROR(status)) { + BS->FreePages(addr, pages); + printf("%s: GetMemoryMap error %lu\n", __func__, + DECODE_ERROR(status)); + return (EINVAL); } if (!exit_bs)