From patchwork Wed Mar 13 15:07:42 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ross Lagerwall X-Patchwork-Id: 13591490 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 0C96AC54E66 for ; Wed, 13 Mar 2024 15:06:52 +0000 (UTC) Received: from list by lists.xenproject.org with outflank-mailman.692517.1079738 (Exim 4.92) (envelope-from ) id 1rkQBo-0007T7-20; Wed, 13 Mar 2024 15:06:44 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version Received: by outflank-mailman (output) from mailman id 692517.1079738; Wed, 13 Mar 2024 15:06:44 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1rkQBn-0007T0-Vb; Wed, 13 Mar 2024 15:06:43 +0000 Received: by outflank-mailman (input) for mailman id 692517; Wed, 13 Mar 2024 15:06:42 +0000 Received: from se1-gles-flk1-in.inumbo.com ([94.247.172.50] helo=se1-gles-flk1.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1rkQBm-0007E2-OD for xen-devel@lists.xenproject.org; Wed, 13 Mar 2024 15:06:42 +0000 Received: from mail-qk1-x734.google.com (mail-qk1-x734.google.com [2607:f8b0:4864:20::734]) by se1-gles-flk1.inumbo.com (Halon) with ESMTPS id 4bc200d4-e14b-11ee-a1ee-f123f15fe8a2; Wed, 13 Mar 2024 16:06:41 +0100 (CET) Received: by mail-qk1-x734.google.com with SMTP id af79cd13be357-789cd0c402dso28402885a.2 for ; Wed, 13 Mar 2024 08:06:41 -0700 (PDT) Received: from rossla-lxenia.eng.citrite.net ([185.25.67.249]) by smtp.gmail.com with ESMTPSA id p10-20020a0ccb8a000000b0068fba49ae81sm4786811qvk.57.2024.03.13.08.06.38 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 13 Mar 2024 08:06:38 -0700 (PDT) X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" X-Inumbo-ID: 4bc200d4-e14b-11ee-a1ee-f123f15fe8a2 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=citrix.com; s=google; t=1710342400; x=1710947200; darn=lists.xenproject.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=KAyEylEkZ+K2w5SdFVwnvdxOdsHKUOMCQVTI6rsesLI=; b=A3nMThb6X9zfnpKvr/5hGP8Z5RPtr8PlieTMZ4RqzgDUxeza9L/uzxZJmp5hagIcfa Ufl1YULVEAIkziSzAdh/OAf2xs4de5YubDI7z5B64VL4Ws/jm36+TJ8lKqjevYdLNLS9 oKnpwhedMo7fwLsRiQ0vdUc3U/i0HEjFDjNFs= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1710342400; x=1710947200; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=KAyEylEkZ+K2w5SdFVwnvdxOdsHKUOMCQVTI6rsesLI=; b=vQLnsqTgt/PSiWX4ATZTn3neD+QhgoQyxY6QuKhSCLKX7Bc0pAGF2SZzxnCc0cMnIG wk6yL0Gk3osJpZJAd4+wI+XVvNehNBF4woxL5zhAZOAJXqXUhk16xewLRYpcvHqRHLbq 5X+/6Zxy3gzjxbzHl8V4VYpnfR10gPHYZGS7AQWWvmKJiNjAlDktp7HTDiuXFS47ptoZ DKpCTp3L1hQ4W8DXfllBpOjDl3YpSYIYBoIwyAe++BMCPZDgyMOBCmeXlsUxrKQDJPrL SxDKVLtVUkLoz9HlMR2uHZHWjse35VWCPD05Ji58cdZRD9NYbsjlsMHJXly/UtcKyfX7 0a9A== X-Gm-Message-State: AOJu0YzBOWgIXaBWrEGMCxYYZ8Y1VySfrWTchVdxxlb/tj66OKmBEnJS dIUhpxR27oADd6SSfSivEcBRIJ3sMp36gsAEWiRLtSfg4hI0ckhGt0Wf8ebBN8xn7tIX71cOJNU OwTyt X-Google-Smtp-Source: AGHT+IHAOg2qe/MwH4SNZCYldAKrSK+zeLn7ifIh3S+CftY7/WCiBtrBu5n7dA3H67+lyXstuf2NLA== X-Received: by 2002:a0c:d687:0:b0:691:1cde:e19f with SMTP id k7-20020a0cd687000000b006911cdee19fmr89340qvi.17.1710342399919; Wed, 13 Mar 2024 08:06:39 -0700 (PDT) From: Ross Lagerwall To: grub-devel@gnu.org Cc: xen-devel@lists.xenproject.org, Andrew Cooper , Daniel Kiper , Ross Lagerwall Subject: [PATCH 1/7] multiboot2: Add load type header and support for the PE binary type Date: Wed, 13 Mar 2024 15:07:42 +0000 Message-ID: <20240313150748.791236-2-ross.lagerwall@citrix.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240313150748.791236-1-ross.lagerwall@citrix.com> References: <20240313150748.791236-1-ross.lagerwall@citrix.com> MIME-Version: 1.0 Currently, multiboot2-compatible bootloaders can load ELF binaries and a.out binaries. The presence of the address header tag determines how the bootloader tries to interpret the binary (a.out if the address tag is present else ELF). Add a new load type header tag that explicitly states the type of the binary. Bootloaders should use the binary type specified in the load type tag. If the load type tag is not present, the bootloader should fall back to the previous heuristics. In addition to the existing address and ELF load types, specify a new optional PE binary load type. This new type is a useful addition since PE binaries can be signed and verified (i.e. used with Secure Boot). Signed-off-by: Ross Lagerwall --- doc/multiboot.texi | 39 ++++++++++++++++++++++++++++++++++----- doc/multiboot2.h | 13 +++++++++++++ 2 files changed, 47 insertions(+), 5 deletions(-) diff --git a/doc/multiboot.texi b/doc/multiboot.texi index df8a0d056e76..d12719c744eb 100644 --- a/doc/multiboot.texi +++ b/doc/multiboot.texi @@ -511,11 +511,12 @@ assumes that no bss segment is present. Note: This information does not need to be provided if the kernel image is in @sc{elf} format, but it must be provided if the image is in a.out -format or in some other format. When the address tag is present it must -be used in order to load the image, regardless of whether an @sc{elf} -header is also present. Compliant boot loaders must be able to load -images that are either in @sc{elf} format or contain the address tag -embedded in the Multiboot2 header. +format or in some other format. If the load type tag is not specified +and the address tag is present it must be used in order to load the +image, regardless of whether an @sc{elf} header is also present. +Compliant boot loaders must be able to load images that are either in +@sc{elf} format or contain the address tag embedded in the Multiboot2 +header. @subsection The entry address tag of Multiboot2 header @@ -732,6 +733,34 @@ and @samp{2} means load image at highest possible address but not higher than max_addr. @end table +@node Load type tag +@subsection Load type tag + +@example +@group + +-------------------+ +u16 | type = 11 | +u16 | flags | +u32 | size = 12 | +u32 | load_type | + +-------------------+ +@end group +@end example + +This tag indicates the type of the payload and how the boot loader +should load it. + +The meaning of each field is as follows: + +@table @code +@item load_type +Recognized load types are @samp{0} for address (i.e. load a.out using +the address tag), @samp{1} for ELF, and @samp{2} for PE. Compliant +bootloaders should implement support for a.out and ELF as a minimum. If +this tag is not specified, the boot loader should attempt to load the +payload using the information specified in the address tag if present, +else it should load the payload as an ELF binary. @end table + @node Machine state @section MIPS machine state diff --git a/doc/multiboot2.h b/doc/multiboot2.h index b181607075b2..d4cae05706e4 100644 --- a/doc/multiboot2.h +++ b/doc/multiboot2.h @@ -75,6 +75,7 @@ #define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI32 8 #define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI64 9 #define MULTIBOOT_HEADER_TAG_RELOCATABLE 10 +#define MULTIBOOT_HEADER_TAG_LOAD_TYPE 11 #define MULTIBOOT_ARCHITECTURE_I386 0 #define MULTIBOOT_ARCHITECTURE_MIPS32 4 @@ -179,6 +180,18 @@ struct multiboot_header_tag_relocatable multiboot_uint32_t preference; }; +struct multiboot_header_tag_load_type +{ + multiboot_uint16_t type; + multiboot_uint16_t flags; + multiboot_uint32_t size; +#define MULTIBOOT_LOAD_TYPE_ADDRESS 0 +#define MULTIBOOT_LOAD_TYPE_ELF 1 +#define MULTIBOOT_LOAD_TYPE_PE 2 +#define MULTIBOOT_LOAD_TYPE_TOTAL 3 + multiboot_uint32_t load_type; +}; + struct multiboot_color { multiboot_uint8_t red; From patchwork Wed Mar 13 15:07:43 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ross Lagerwall X-Patchwork-Id: 13591491 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 9E511C54791 for ; Wed, 13 Mar 2024 15:06:52 +0000 (UTC) Received: from list by lists.xenproject.org with outflank-mailman.692518.1079748 (Exim 4.92) (envelope-from ) id 1rkQBp-0007iF-8H; Wed, 13 Mar 2024 15:06:45 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version Received: by outflank-mailman (output) from mailman id 692518.1079748; Wed, 13 Mar 2024 15:06:45 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1rkQBp-0007i6-5W; Wed, 13 Mar 2024 15:06:45 +0000 Received: by outflank-mailman (input) for mailman id 692518; Wed, 13 Mar 2024 15:06:44 +0000 Received: from se1-gles-flk1-in.inumbo.com ([94.247.172.50] helo=se1-gles-flk1.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1rkQBo-0007E2-HQ for xen-devel@lists.xenproject.org; Wed, 13 Mar 2024 15:06:44 +0000 Received: from mail-qv1-xf2c.google.com (mail-qv1-xf2c.google.com [2607:f8b0:4864:20::f2c]) by se1-gles-flk1.inumbo.com (Halon) with ESMTPS id 4cbb0028-e14b-11ee-a1ee-f123f15fe8a2; Wed, 13 Mar 2024 16:06:42 +0100 (CET) Received: by mail-qv1-xf2c.google.com with SMTP id 6a1803df08f44-690ca2d2c5bso24721776d6.2 for ; Wed, 13 Mar 2024 08:06:42 -0700 (PDT) Received: from rossla-lxenia.eng.citrite.net ([185.25.67.249]) by smtp.gmail.com with ESMTPSA id p10-20020a0ccb8a000000b0068fba49ae81sm4786811qvk.57.2024.03.13.08.06.40 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 13 Mar 2024 08:06:40 -0700 (PDT) X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" X-Inumbo-ID: 4cbb0028-e14b-11ee-a1ee-f123f15fe8a2 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=citrix.com; s=google; t=1710342401; x=1710947201; darn=lists.xenproject.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=vzi7gexZvWQMljijVlDNbWhNKDms1QxVcPrC/wEDf/o=; b=gsWUT/FF4FT6Ape+kidsf/9F6+xWleVUxMvN/8JxfiNidnrjfKqKy4ylBmHC0VWI/9 4JLy/g+Tu0vprr09BW9ZuGDeVSVXsXjxyLVm2sgPnnuQPVWutLpsJ8rvEWg5F9LFJN03 VxL4nV+NtVEVaqiyqTq79OuwgN35Skb74iDBE= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1710342401; x=1710947201; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=vzi7gexZvWQMljijVlDNbWhNKDms1QxVcPrC/wEDf/o=; b=BdXcQeNxWCtNot8q7RqyCHO3pDZuAjnC5dy/Zj6aQbAfKerPecbQxfabBvjyyL9fcK hlHiqEJ3qX5fC+WMq24a4C67xlo8X4nxgjC/s5cuOKgbd3UFVPPXsm2gVoak72robC77 20DBAi1VHilYvzEg8a9/Fo71aPJHD+piyUZWcBqbjrowLfQ77w8fMt6Mq/VWHuGYrcbT Hu0XZBo4F6hYTu+GWYLf84MRgf42C1Xm+h31RlDC/h8RZEKM1TNTJXW2nRSWMVu8AqoZ MGE+DNTTQnH4tt8gLYiMEhSdL5jJ5sERn/ELrnCFcladAwf6+ipAr9x08wKsZWM17f3A HpJg== X-Gm-Message-State: AOJu0YynjNJ2udcjijZ8QBENL+eD6hqDaj3hqXaDNr5Yx6FDQH7jwX+x iRTrI+GM0xoCtbPGA3muzgBA8afM2Qw4iep5Lhp8AluwW7Zzm7iblRw+u1mbCeNraXuwUIViCZJ XlOLN X-Google-Smtp-Source: AGHT+IH9fmrW3gMuuJAfjFbZjjqE4vpclj5uYDw95WuKdz/9FlbDNxdI+xMFfZNCxETx42Aw/ybjQA== X-Received: by 2002:a05:6214:9c7:b0:690:c863:f06d with SMTP id dp7-20020a05621409c700b00690c863f06dmr68485qvb.40.1710342401639; Wed, 13 Mar 2024 08:06:41 -0700 (PDT) From: Ross Lagerwall To: grub-devel@gnu.org Cc: xen-devel@lists.xenproject.org, Andrew Cooper , Daniel Kiper , Ross Lagerwall Subject: [PATCH 2/7] multiboot2: Allow 64-bit entry tags Date: Wed, 13 Mar 2024 15:07:43 +0000 Message-ID: <20240313150748.791236-3-ross.lagerwall@citrix.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240313150748.791236-1-ross.lagerwall@citrix.com> References: <20240313150748.791236-1-ross.lagerwall@citrix.com> MIME-Version: 1.0 Binaries may be built with entry points above 4G. While bootloaders may relocate them below 4G, it should be possible for the binary to specify those entry points. Therefore, extend the multiboot2 protocol such that 64 bit addresses are allowed for entry points. The extension is done in a backwards-compatible way. Signed-off-by: Ross Lagerwall --- doc/multiboot.texi | 32 +++++++++++++++++++------------- doc/multiboot2.h | 6 +++++- 2 files changed, 24 insertions(+), 14 deletions(-) diff --git a/doc/multiboot.texi b/doc/multiboot.texi index d12719c744eb..049afab53c1f 100644 --- a/doc/multiboot.texi +++ b/doc/multiboot.texi @@ -522,12 +522,12 @@ header. @example @group - +-------------------+ -u16 | type = 3 | -u16 | flags | -u32 | size | -u32 | entry_addr | - +-------------------+ + +-------------------+ +u16 | type = 3 | +u16 | flags | +u32 | size | +u32 / u64 | entry_addr | + +-------------------+ @end group @end example @@ -538,7 +538,10 @@ The meaning of each is as follows: @item entry_addr The physical address to which the boot loader should jump in order to -start running the operating system. +start running the operating system. @samp{entry_addr} may be specified +either as a @samp{u32} or @samp{u64}. The bootloader should use the +header size to determine the size of @samp{entry_addr}. + @end table @subsection EFI i386 entry address tag of Multiboot2 header @@ -573,12 +576,12 @@ tag of Multiboot2 header are ignored. @example @group - +-------------------+ -u16 | type = 9 | -u16 | flags | -u32 | size | -u32 | entry_addr | - +-------------------+ + +-------------------+ +u16 | type = 9 | +u16 | flags | +u32 | size | +u32 / u64 | entry_addr | + +-------------------+ @end group @end example @@ -594,6 +597,9 @@ is as follows: @item entry_addr The physical address to which the boot loader should jump in order to start running EFI amd64 compatible operating system code. +@samp{entry_addr} may be specified either as a @samp{u32} or @samp{u64}. +The bootloader should use the header size to determine the size of +@samp{entry_addr}. @end table This tag is taken into account only on EFI amd64 platforms diff --git a/doc/multiboot2.h b/doc/multiboot2.h index d4cae05706e4..a994a7b28b02 100644 --- a/doc/multiboot2.h +++ b/doc/multiboot2.h @@ -141,7 +141,11 @@ struct multiboot_header_tag_entry_address multiboot_uint16_t type; multiboot_uint16_t flags; multiboot_uint32_t size; - multiboot_uint32_t entry_addr; + union + { + multiboot_uint32_t entry_addr32; + multiboot_uint64_t entry_addr64; + }; }; struct multiboot_header_tag_console_flags From patchwork Wed Mar 13 15:07:44 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ross Lagerwall X-Patchwork-Id: 13591492 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 67272C54E66 for ; Wed, 13 Mar 2024 15:06:56 +0000 (UTC) Received: from list by lists.xenproject.org with outflank-mailman.692519.1079759 (Exim 4.92) (envelope-from ) id 1rkQBq-0007xv-GW; Wed, 13 Mar 2024 15:06:46 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version Received: by outflank-mailman (output) from mailman id 692519.1079759; Wed, 13 Mar 2024 15:06:46 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1rkQBq-0007xk-Cr; Wed, 13 Mar 2024 15:06:46 +0000 Received: by outflank-mailman (input) for mailman id 692519; Wed, 13 Mar 2024 15:06:45 +0000 Received: from se1-gles-sth1-in.inumbo.com ([159.253.27.254] helo=se1-gles-sth1.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1rkQBp-0007DJ-6s for xen-devel@lists.xenproject.org; Wed, 13 Mar 2024 15:06:45 +0000 Received: from mail-qk1-x730.google.com (mail-qk1-x730.google.com [2607:f8b0:4864:20::730]) by se1-gles-sth1.inumbo.com (Halon) with ESMTPS id 4dbf5a7f-e14b-11ee-afdd-a90da7624cb6; Wed, 13 Mar 2024 16:06:44 +0100 (CET) Received: by mail-qk1-x730.google.com with SMTP id af79cd13be357-7882b1e87c4so265648985a.1 for ; Wed, 13 Mar 2024 08:06:44 -0700 (PDT) Received: from rossla-lxenia.eng.citrite.net ([185.25.67.249]) by smtp.gmail.com with ESMTPSA id p10-20020a0ccb8a000000b0068fba49ae81sm4786811qvk.57.2024.03.13.08.06.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 13 Mar 2024 08:06:42 -0700 (PDT) X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" X-Inumbo-ID: 4dbf5a7f-e14b-11ee-afdd-a90da7624cb6 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=citrix.com; s=google; t=1710342403; x=1710947203; darn=lists.xenproject.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=aZp28TJaho7bmYkQTjxVyJZGgKr3RuW+VThi/ld76Pc=; b=UBhZVWkdwAY5EIGqr5C+0vGeM9DCHRE98Gok0s57e2NnoFu8fPnyVav7c3zmuFQBs4 TcAxlMdyYIznoAr+se7PnRoFaTomy3vq+LAW0ZNdYhKqS7my9YiRCsEtnYCXPCoqom6I Jh2J2U4j/bqfg25Te+n/hgGHIidhYgVwkhZ3g= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1710342403; x=1710947203; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=aZp28TJaho7bmYkQTjxVyJZGgKr3RuW+VThi/ld76Pc=; b=AhRLAAqGcIJ1wjlg3L+kPabU+FICX+5EhF60EtXcLGhNDVgf3TuJVzTortbKxdKVjX 8H055d44/K7WA40a4AUY1ynYrOlYHZ7TrHkC7wubp+MfTGAOYQ5kiVqF/aSqjyNamKML gVfGJc3PtJ4pF6cdYzK2iKuRi7yzYi/mbwNF3HfL5FyZkwi0M0Say0EmG1JeFhh5hLgY 3E2XidAhdsISZ3agBKF3lOaIe1M3HkuxEtyhVYpZAL/qDWeDAnMFdeJM5bhuSVaDpZVb gDz0ciyYqp/I3YYFNk9EYHhnKa7//3TfgsR4E0SaHXuYnDIo1REGO4+yj0TdoGJ9iWGX RvIQ== X-Gm-Message-State: AOJu0Yzu5y/gKza3/dixrSm90RHQaE4DFMkCiVGSYHSa8OMf6O8sFOLg T2+jLg06HgteOEQ8fjXvAcmcvZh20SAyDjU9rwunGgVtHqYFfI/4i4eFEcM9ag== X-Google-Smtp-Source: AGHT+IFC1t3oGaIaWTD7qAvoHPvFddvbbLTuvdcaC4WasfMYFmVyprTkfSeTUbh1nwaatINz4YBo+Q== X-Received: by 2002:a0c:9c8c:0:b0:690:e2b5:9219 with SMTP id i12-20020a0c9c8c000000b00690e2b59219mr119040qvf.22.1710342403310; Wed, 13 Mar 2024 08:06:43 -0700 (PDT) From: Ross Lagerwall To: grub-devel@gnu.org Cc: xen-devel@lists.xenproject.org, Andrew Cooper , Daniel Kiper , Ross Lagerwall Subject: [PATCH 3/7] multiboot2: Add support for the load type header tag Date: Wed, 13 Mar 2024 15:07:44 +0000 Message-ID: <20240313150748.791236-4-ross.lagerwall@citrix.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240313150748.791236-1-ross.lagerwall@citrix.com> References: <20240313150748.791236-1-ross.lagerwall@citrix.com> MIME-Version: 1.0 The binary may expose its type using the load type header tag. Implement it according to the specification. Signed-off-by: Ross Lagerwall --- grub-core/loader/multiboot_mbi2.c | 45 ++++++++++++++++++++++++++++--- include/grub/multiboot2.h | 1 + include/multiboot2.h | 13 +++++++++ 3 files changed, 56 insertions(+), 3 deletions(-) diff --git a/grub-core/loader/multiboot_mbi2.c b/grub-core/loader/multiboot_mbi2.c index 00a48413c013..6ef4f265070a 100644 --- a/grub-core/loader/multiboot_mbi2.c +++ b/grub-core/loader/multiboot_mbi2.c @@ -119,10 +119,12 @@ grub_multiboot2_load (grub_file_t file, const char *filename) grub_uint32_t console_required = 0; struct multiboot_header_tag_framebuffer *fbtag = NULL; int accepted_consoles = GRUB_MULTIBOOT2_CONSOLE_EGA_TEXT; + struct multiboot_header_tag_load_type *load_type_tag; mbi_load_data_t mld; mld.mbi_ver = 2; mld.relocatable = 0; + mld.load_type = MULTIBOOT_LOAD_TYPE_TOTAL; mld.buffer = grub_malloc (MULTIBOOT_SEARCH); if (!mld.buffer) @@ -258,6 +260,17 @@ grub_multiboot2_load (grub_file_t file, const char *filename) #endif break; + case MULTIBOOT_HEADER_TAG_LOAD_TYPE: + load_type_tag = (struct multiboot_header_tag_load_type *) tag; + mld.load_type = load_type_tag->load_type; + if (mld.load_type >= MULTIBOOT_LOAD_TYPE_TOTAL) + { + grub_free (mld.buffer); + return grub_error (GRUB_ERR_UNKNOWN_OS, + "unsupported load type: %u", load_type_tag->load_type); + } + break; + default: if (! (tag->flags & MULTIBOOT_HEADER_TAG_OPTIONAL)) { @@ -268,14 +281,32 @@ grub_multiboot2_load (grub_file_t file, const char *filename) break; } - if (addr_tag && !entry_specified && !(keep_bs && efi_entry_specified)) + if (mld.load_type == MULTIBOOT_LOAD_TYPE_ADDRESS && !addr_tag) + { + grub_free (mld.buffer); + return grub_error (GRUB_ERR_UNKNOWN_OS, + "load type address without address tag"); + } + if (mld.load_type < MULTIBOOT_LOAD_TYPE_TOTAL && + mld.load_type != MULTIBOOT_LOAD_TYPE_ADDRESS && addr_tag) + { + grub_free (mld.buffer); + return grub_error (GRUB_ERR_UNKNOWN_OS, + "address tag specified but load type doesn't match"); + } + if (mld.load_type == MULTIBOOT_LOAD_TYPE_TOTAL) + mld.load_type = addr_tag ? MULTIBOOT_LOAD_TYPE_ADDRESS : MULTIBOOT_LOAD_TYPE_ELF; + + if (mld.load_type == MULTIBOOT_LOAD_TYPE_ADDRESS && !entry_specified && + !(keep_bs && efi_entry_specified)) { grub_free (mld.buffer); return grub_error (GRUB_ERR_UNKNOWN_OS, "load address tag without entry address tag"); } - if (addr_tag) + switch (mld.load_type) { + case MULTIBOOT_LOAD_TYPE_ADDRESS: { grub_uint64_t load_addr = (addr_tag->load_addr + 1) ? addr_tag->load_addr : (addr_tag->header_addr @@ -343,8 +374,9 @@ grub_multiboot2_load (grub_file_t file, const char *filename) if (addr_tag->bss_end_addr) grub_memset ((grub_uint8_t *) source + load_size, 0, addr_tag->bss_end_addr - load_addr - load_size); + break; } - else + case MULTIBOOT_LOAD_TYPE_ELF: { mld.file = file; mld.filename = filename; @@ -355,7 +387,14 @@ grub_multiboot2_load (grub_file_t file, const char *filename) grub_free (mld.buffer); return err; } + break; } + case MULTIBOOT_LOAD_TYPE_PE: + grub_fatal ("Unsupported load type: %u\n", mld.load_type); + default: + /* should be impossible */ + grub_fatal ("Unknown load type: %u\n", mld.load_type); + } load_base_addr = mld.load_base_addr; diff --git a/include/grub/multiboot2.h b/include/grub/multiboot2.h index b90aa6989674..1f6d4fc9e336 100644 --- a/include/grub/multiboot2.h +++ b/include/grub/multiboot2.h @@ -89,6 +89,7 @@ struct mbi_load_data grub_uint32_t link_base_addr; grub_uint32_t load_base_addr; int avoid_efi_boot_services; + grub_uint32_t load_type; }; typedef struct mbi_load_data mbi_load_data_t; diff --git a/include/multiboot2.h b/include/multiboot2.h index a039aa0439aa..f4377bf7b394 100644 --- a/include/multiboot2.h +++ b/include/multiboot2.h @@ -74,6 +74,7 @@ #define MULTIBOOT_HEADER_TAG_EFI_BS 7 #define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI64 9 #define MULTIBOOT_HEADER_TAG_RELOCATABLE 10 +#define MULTIBOOT_HEADER_TAG_LOAD_TYPE 11 #define MULTIBOOT2_ARCHITECTURE_I386 0 #define MULTIBOOT2_ARCHITECTURE_MIPS32 4 @@ -178,6 +179,18 @@ struct multiboot_header_tag_relocatable multiboot_uint32_t preference; }; +struct multiboot_header_tag_load_type +{ + multiboot_uint16_t type; + multiboot_uint16_t flags; + multiboot_uint32_t size; +#define MULTIBOOT_LOAD_TYPE_ADDRESS 0 +#define MULTIBOOT_LOAD_TYPE_ELF 1 +#define MULTIBOOT_LOAD_TYPE_PE 2 +#define MULTIBOOT_LOAD_TYPE_TOTAL 3 + multiboot_uint32_t load_type; +}; + struct multiboot_color { multiboot_uint8_t red; From patchwork Wed Mar 13 15:07:45 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ross Lagerwall X-Patchwork-Id: 13591495 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id D68F3C54791 for ; Wed, 13 Mar 2024 15:06:59 +0000 (UTC) Received: from list by lists.xenproject.org with outflank-mailman.692521.1079774 (Exim 4.92) (envelope-from ) id 1rkQBv-0008Lg-4J; Wed, 13 Mar 2024 15:06:51 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version Received: by outflank-mailman (output) from mailman id 692521.1079774; Wed, 13 Mar 2024 15:06:51 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1rkQBu-0008Kj-Uw; Wed, 13 Mar 2024 15:06:50 +0000 Received: by outflank-mailman (input) for mailman id 692521; Wed, 13 Mar 2024 15:06:49 +0000 Received: from se1-gles-flk1-in.inumbo.com ([94.247.172.50] helo=se1-gles-flk1.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1rkQBt-0007E2-3u for xen-devel@lists.xenproject.org; Wed, 13 Mar 2024 15:06:49 +0000 Received: from mail-qk1-x732.google.com (mail-qk1-x732.google.com [2607:f8b0:4864:20::732]) by se1-gles-flk1.inumbo.com (Halon) with ESMTPS id 4efe53db-e14b-11ee-a1ee-f123f15fe8a2; Wed, 13 Mar 2024 16:06:46 +0100 (CET) Received: by mail-qk1-x732.google.com with SMTP id af79cd13be357-7885bb1b760so52683685a.0 for ; Wed, 13 Mar 2024 08:06:46 -0700 (PDT) Received: from rossla-lxenia.eng.citrite.net ([185.25.67.249]) by smtp.gmail.com with ESMTPSA id p10-20020a0ccb8a000000b0068fba49ae81sm4786811qvk.57.2024.03.13.08.06.43 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 13 Mar 2024 08:06:44 -0700 (PDT) X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" X-Inumbo-ID: 4efe53db-e14b-11ee-a1ee-f123f15fe8a2 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=citrix.com; s=google; t=1710342405; x=1710947205; darn=lists.xenproject.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=fnCQ6iGEQlGDwp0KgZ7SdE2CyEyUyRyRTqUnAJN4R94=; b=p0Q3IN0r0VAcp9VMU56fx808dfWqDJzY2o7qhjk57+TKAKazXNwsTOp/g7IuzXe8LR VED4feMAUpfywv1OpqVS61kT/3sTnhGfbzkJjBx9av30U3oFWcDBg1lp55VMucuh6lLN njmVXmX3T3NDWZVJ1cDpO2YhdcDN+mvqFMpEM= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1710342405; x=1710947205; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=fnCQ6iGEQlGDwp0KgZ7SdE2CyEyUyRyRTqUnAJN4R94=; b=BY5Mrus7BsEhKzDahT6hgAsg335Ae5tmWR1aJwp84MBXnx+znTDqxy7m0H8dis9vKZ /9HIbvqFgs/X7FkBeo2FnU8yUG6x1NdBSaNeWFowzaChU4i1JJm5FJ08AdDkpGPyKYdx bfUsXHNpoUvnqdoCWFhebbHkOSYYdv99UonyQaUb2YOHLFCQk609LHCBrgV439L8kiiO iqIoolUeTNPpZucrxd5yWKo7m7lzSsrBUbU8Ra/SeOK8vOPSnPnGKeucPRRR/YI+BmUM wn4eOzUag6CxCJNy8FR801WkwWqRrUMI6KGCNAREe6QiW7DMl+BsZoFo/RNPLIkYHWdo zR6Q== X-Gm-Message-State: AOJu0Yw21eT30ccE7MG2N2L2q0Ye9IhQ4qQ7JjefH5HOH4T9m54RAMCx lYs9L6N7YWHopH+Q4s63isXi6AtYkw7UKU9Xw4cBMTd3MSC8LO1cf8+xXP0Swgy6VBYWZ4KORNt 6rQ== X-Google-Smtp-Source: AGHT+IFtTSlpAbXFsRrwJaGE4XLyNfpqFwXS0lTUp2QVeXs6Lh+rmtvs+mnKLVyFDIP0W8U3Vm+FmQ== X-Received: by 2002:a0c:fa87:0:b0:690:d102:a6a8 with SMTP id o7-20020a0cfa87000000b00690d102a6a8mr64516qvn.42.1710342405258; Wed, 13 Mar 2024 08:06:45 -0700 (PDT) From: Ross Lagerwall To: grub-devel@gnu.org Cc: xen-devel@lists.xenproject.org, Andrew Cooper , Daniel Kiper , Ross Lagerwall Subject: [PATCH 4/7] multiboot2: Add PE load support Date: Wed, 13 Mar 2024 15:07:45 +0000 Message-ID: <20240313150748.791236-5-ross.lagerwall@citrix.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240313150748.791236-1-ross.lagerwall@citrix.com> References: <20240313150748.791236-1-ross.lagerwall@citrix.com> MIME-Version: 1.0 Add the ability to load multiboot binaries in PE format. This allows the binaries to be signed and verified. Signed-off-by: Ross Lagerwall --- grub-core/Makefile.core.def | 1 + grub-core/loader/multiboot_mbi2.c | 15 +- grub-core/loader/multiboot_pe.c | 694 ++++++++++++++++++++++++++++++ include/grub/efi/pe32.h | 64 +++ include/grub/multiboot2.h | 3 + 5 files changed, 775 insertions(+), 2 deletions(-) create mode 100644 grub-core/loader/multiboot_pe.c diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 1571421d7e84..34697ba58171 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -1815,6 +1815,7 @@ module = { common = loader/multiboot.c; common = loader/multiboot_mbi2.c; + common = loader/multiboot_pe.c; enable = x86; enable = i386_xen_pvh; enable = mips; diff --git a/grub-core/loader/multiboot_mbi2.c b/grub-core/loader/multiboot_mbi2.c index 6ef4f265070a..3ec96e2f29b9 100644 --- a/grub-core/loader/multiboot_mbi2.c +++ b/grub-core/loader/multiboot_mbi2.c @@ -389,8 +389,19 @@ grub_multiboot2_load (grub_file_t file, const char *filename) } break; } - case MULTIBOOT_LOAD_TYPE_PE: - grub_fatal ("Unsupported load type: %u\n", mld.load_type); + case MULTIBOOT_LOAD_TYPE_PE: + { + mld.file = file; + mld.filename = filename; + mld.avoid_efi_boot_services = keep_bs; + err = grub_multiboot2_load_pe (&mld); + if (err) + { + grub_free (mld.buffer); + return err; + } + break; + } default: /* should be impossible */ grub_fatal ("Unknown load type: %u\n", mld.load_type); diff --git a/grub-core/loader/multiboot_pe.c b/grub-core/loader/multiboot_pe.c new file mode 100644 index 000000000000..7f418348ac70 --- /dev/null +++ b/grub-core/loader/multiboot_pe.c @@ -0,0 +1,694 @@ +/* + * Significant portions of this code are derived from the Fedora GRUB patch + * "0007-Add-secureboot-support-on-efi-chainloader.patch" which is in turn + * derived from the PE loading code in Shim. The license is reproduced below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Copyright Peter Jones + * + * Modifications: + * + * Copyright (c) 2024. Cloud Software Group, Inc. + */ + +#include +#include +#include + +static int +image_is_64_bit (grub_pe_header_t *pe_hdr) +{ + /* .Magic is the same offset in all cases */ + return pe_hdr->pe32plus.optional_header.magic == GRUB_PE32_PE64_MAGIC; +} + +static const grub_uint16_t machine_type __attribute__((__unused__)) = +#if defined(__x86_64__) + GRUB_PE32_MACHINE_X86_64; +#elif defined(__aarch64__) + GRUB_PE32_MACHINE_ARM64; +#elif defined(__arm__) + GRUB_PE32_MACHINE_ARMTHUMB_MIXED; +#elif defined(__i386__) || defined(__i486__) || defined(__i686__) + GRUB_PE32_MACHINE_I386; +#elif defined(__ia64__) + GRUB_PE32_MACHINE_IA64; +#elif defined(__riscv) && (__riscv_xlen == 32) + GRUB_PE32_MACHINE_RISCV32; +#elif defined(__riscv) && (__riscv_xlen == 64) + GRUB_PE32_MACHINE_RISCV64; +#else +#error this architecture is not supported by grub2 +#endif + +static int +image_is_loadable(grub_pe_header_t *pe_hdr) +{ + /* + * Check the machine type matches the binary and that we recognize + * the magic number. + */ + return (pe_hdr->pe32.coff_header.machine == machine_type || + (pe_hdr->pe32.coff_header.machine == GRUB_PE32_MACHINE_X86_64 && + machine_type == GRUB_PE32_MACHINE_I386)) && + (pe_hdr->pe32plus.optional_header.magic == GRUB_PE32_PE32_MAGIC || + pe_hdr->pe32plus.optional_header.magic == GRUB_PE32_PE64_MAGIC); +} + +/* + * Read the binary header and grab appropriate information from it + */ +static grub_err_t +read_header(void *data, unsigned int datasize, + pe_coff_loader_image_context_t *context) +{ + grub_pe32_msdos_header_t *dos_hdr = data; + grub_pe_header_t *pe_hdr = data; + unsigned long header_without_data_dir, section_header_offset, opt_header_size; + unsigned long file_alignment = 0; + + if (datasize < sizeof (pe_hdr->pe32)) + { + grub_error (GRUB_ERR_OUT_OF_RANGE, "Invalid image"); + return GRUB_ERR_OUT_OF_RANGE; + } + + if (dos_hdr->e_magic == GRUB_PE32_MAGIC) + pe_hdr = (grub_pe_header_t *)((char *)data + dos_hdr->e_lfanew); + + if (!image_is_loadable(pe_hdr)) + { + grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "Platform does not support this image"); + return GRUB_ERR_NOT_IMPLEMENTED_YET; + } + + if (image_is_64_bit(pe_hdr)) + { + context->number_of_rva_and_sizes = pe_hdr->pe32plus.optional_header.num_data_directories; + context->size_of_headers = pe_hdr->pe32plus.optional_header.header_size; + context->image_size = pe_hdr->pe32plus.optional_header.image_size; + context->section_alignment = pe_hdr->pe32plus.optional_header.section_alignment; + file_alignment = pe_hdr->pe32plus.optional_header.file_alignment; + opt_header_size = sizeof(struct grub_pe64_optional_header); + } + else + { + context->number_of_rva_and_sizes = pe_hdr->pe32.optional_header.num_data_directories; + context->size_of_headers = pe_hdr->pe32.optional_header.header_size; + context->image_size = (grub_uint64_t)pe_hdr->pe32.optional_header.image_size; + context->section_alignment = pe_hdr->pe32.optional_header.section_alignment; + file_alignment = pe_hdr->pe32.optional_header.file_alignment; + opt_header_size = sizeof(struct grub_pe32_optional_header); + } + + if (file_alignment % 2 != 0) + { + grub_error (GRUB_ERR_OUT_OF_RANGE, "File Alignment is invalid (%ld)", file_alignment); + return GRUB_ERR_OUT_OF_RANGE; + } + if (file_alignment == 0) + file_alignment = 0x200; + if (context->section_alignment == 0) + context->section_alignment = GRUB_EFI_PAGE_SIZE; + if (context->section_alignment < file_alignment) + context->section_alignment = file_alignment; + + context->number_of_sections = pe_hdr->pe32.coff_header.num_sections; + + if (EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES < context->number_of_rva_and_sizes) + { + grub_error (GRUB_ERR_OUT_OF_RANGE, "Image header too small"); + return GRUB_ERR_OUT_OF_RANGE; + } + + header_without_data_dir = opt_header_size + - sizeof (struct grub_pe32_data_directory) * EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES; + if (((grub_uint32_t)pe_hdr->pe32.coff_header.optional_header_size - header_without_data_dir) != + context->number_of_rva_and_sizes * sizeof (struct grub_pe32_data_directory)) + { + grub_error (GRUB_ERR_OUT_OF_RANGE, "Image header overflows data directory"); + return GRUB_ERR_OUT_OF_RANGE; + } + + section_header_offset = dos_hdr->e_lfanew + + sizeof (grub_uint32_t) + + sizeof (struct grub_pe32_coff_header) + + pe_hdr->pe32.coff_header.optional_header_size; + if (((grub_uint32_t)context->image_size - section_header_offset) / sizeof(struct grub_pe32_section_table) + <= context->number_of_sections) + { + grub_error (GRUB_ERR_OUT_OF_RANGE, "Image sections overflow image size"); + return GRUB_ERR_OUT_OF_RANGE; + } + + if ((context->size_of_headers - section_header_offset) / sizeof(struct grub_pe32_section_table) + < (grub_uint32_t)context->number_of_sections) + { + grub_error (GRUB_ERR_OUT_OF_RANGE, "Image sections overflow section headers"); + return GRUB_ERR_OUT_OF_RANGE; + } + + if ((((grub_uint8_t *)pe_hdr - (grub_uint8_t *)data) + sizeof(grub_pe_header_t)) > datasize) + { + grub_error (GRUB_ERR_OUT_OF_RANGE, "Invalid image"); + return GRUB_ERR_OUT_OF_RANGE; + } + + if (pe_hdr->pe32.signature[0] != 'P' || + pe_hdr->pe32.signature[1] != 'E' || + pe_hdr->pe32.signature[2] != 0x00 || + pe_hdr->pe32.signature[3] != 0x00) + { + grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "Unsupported image type"); + return GRUB_ERR_NOT_IMPLEMENTED_YET; + } + + context->pe_hdr = pe_hdr; + + if (image_is_64_bit(pe_hdr)) + { + context->image_address = pe_hdr->pe32plus.optional_header.image_base; + context->entry_point = pe_hdr->pe32plus.optional_header.entry_addr; + context->reloc_dir = &pe_hdr->pe32plus.optional_header.base_relocation_table; + context->sec_dir = &pe_hdr->pe32plus.optional_header.certificate_table; + } + else + { + context->image_address = pe_hdr->pe32.optional_header.image_base; + context->entry_point = pe_hdr->pe32.optional_header.entry_addr; + context->reloc_dir = &pe_hdr->pe32.optional_header.base_relocation_table; + context->sec_dir = &pe_hdr->pe32.optional_header.certificate_table; + } + + context->first_section = (struct grub_pe32_section_table *)((char *)pe_hdr + + pe_hdr->pe32.coff_header.optional_header_size + + sizeof(grub_uint32_t) + sizeof(struct grub_pe32_coff_header)); + + if (context->image_size < context->size_of_headers) + { + grub_error (GRUB_ERR_OUT_OF_RANGE, "Invalid image"); + return GRUB_ERR_OUT_OF_RANGE; + } + + if ((unsigned long)((grub_uint8_t *)context->sec_dir - (grub_uint8_t *)data) > + (datasize - sizeof(struct grub_pe32_data_directory))) + { + grub_error (GRUB_ERR_OUT_OF_RANGE, "Invalid image"); + return GRUB_ERR_OUT_OF_RANGE; + } + return GRUB_ERR_NONE; +} + +static grub_phys_addr_t +image_address (grub_phys_addr_t image, grub_uint64_t sz, grub_uint64_t addr) +{ + if (addr > sz) + return 0; + + return image + addr; +} + +static grub_err_t +relocate_coff (pe_coff_loader_image_context_t *context, + struct grub_pe32_section_table *section, + grub_phys_addr_t phys_addr, grub_uint8_t *virt_addr, + mbi_load_data_t *mld) +{ + struct grub_pe32_data_directory *reloc_base, *reloc_base_end; + grub_uint8_t *reloc_buffer; + grub_uint64_t adjust; + struct grub_pe32_fixup_block *reloc, *reloc_end; + grub_uint8_t *fixup, *fixup_base; + grub_uint16_t *fixup_16; + grub_uint32_t *fixup_32; + grub_uint64_t *fixup_64; + int n = 0; + grub_err_t ret = GRUB_ERR_NONE; + + if (image_is_64_bit (context->pe_hdr)) + context->pe_hdr->pe32plus.optional_header.image_base = + (grub_uint64_t)(unsigned long)phys_addr; + else + context->pe_hdr->pe32.optional_header.image_base = + (grub_uint32_t)(unsigned long)phys_addr; + + /* Alright, so here's how this works: + * + * context->reloc_dir gives us two things: + * - the VA the table of base relocation blocks are (maybe) to be + * mapped at (reloc_dir->rva) + * - the virtual size (reloc_dir->size) + * + * The .reloc section (section here) gives us some other things: + * - the name! kind of. (section->name) + * - the virtual size (section->virtual_size), which should be the same + * as RelocDir->Size + * - the virtual address (section->virtual_address) + * - the file section size (section->raw_data_size), which is + * a multiple of optional_header->file_alignment. Only useful for image + * validation, not really useful for iteration bounds. + * - the file address (section->raw_data_offset) + * - a bunch of stuff we don't use that's 0 in our binaries usually + * - Flags (section->characteristics) + * + * and then the thing that's actually at the file address is an array + * of struct grub_pe32_fixup_block structs with some values packed behind + * them. The block_size field of this structure includes the + * structure itself, and adding it to that structure's address will + * yield the next entry in the array. + */ + + reloc_buffer = grub_malloc (section->virtual_size); + if (!reloc_buffer) + return grub_errno; + + if (grub_file_seek (mld->file, section->raw_data_offset) == (grub_off_t) -1) + { + ret = grub_errno; + goto out; + } + + if (grub_file_read (mld->file, reloc_buffer, section->virtual_size) + != (grub_ssize_t) section->virtual_size) + { + if (!grub_errno) + { + grub_error (GRUB_ERR_FILE_READ_ERROR, "premature end of file %s", + mld->filename); + ret = GRUB_ERR_FILE_READ_ERROR; + } + else + ret = grub_errno; + goto out; + } + + reloc_base = (struct grub_pe32_data_directory *)reloc_buffer; + reloc_base_end = (struct grub_pe32_data_directory *)(reloc_buffer + section->virtual_size); + + grub_dprintf ("multiboot_loader", "relocate_coff(): reloc_base %p reloc_base_end %p\n", + reloc_base, reloc_base_end); + + if (!reloc_base && !reloc_base_end) + return GRUB_ERR_NONE; + + if (!reloc_base || !reloc_base_end) + { + grub_error (GRUB_ERR_BAD_ARGUMENT, "Reloc table overflows binary"); + return GRUB_ERR_BAD_ARGUMENT; + } + + adjust = (grub_uint64_t)(grub_efi_uintn_t)phys_addr - context->image_address; + if (adjust == 0) + return GRUB_ERR_NONE; + + while (reloc_base < reloc_base_end) + { + grub_uint16_t *entry; + reloc = (struct grub_pe32_fixup_block *)((char*)reloc_base); + + if ((reloc_base->size == 0) || + (reloc_base->size > context->reloc_dir->size)) + { + grub_error (GRUB_ERR_BAD_ARGUMENT, + "Reloc %d block size %d is invalid\n", n, + reloc_base->size); + ret = GRUB_ERR_BAD_ARGUMENT; + goto out; + } + + entry = &reloc->entries[0]; + reloc_end = (struct grub_pe32_fixup_block *) + ((char *)reloc_base + reloc_base->size); + + if ((grub_uint8_t *)reloc_end < reloc_buffer || + (grub_uint8_t *)reloc_end > (reloc_buffer + section->virtual_size)) + { + grub_error (GRUB_ERR_BAD_ARGUMENT, "Reloc entry %d overflows binary", + n); + return GRUB_ERR_BAD_ARGUMENT; + } + + fixup_base = virt_addr + reloc_base->rva; + if (!fixup_base) + { + grub_error (GRUB_ERR_BAD_ARGUMENT, "Reloc %d Invalid fixupbase", n); + ret = GRUB_ERR_BAD_ARGUMENT; + goto out; + } + + while ((void *)entry < (void *)reloc_end) + { + fixup = fixup_base + (*entry & 0xFFF); + switch ((*entry) >> 12) + { + case GRUB_PE32_REL_BASED_ABSOLUTE: + break; + case GRUB_PE32_REL_BASED_HIGH: + fixup_16 = (grub_uint16_t *)fixup; + *fixup_16 = (grub_uint16_t) + (*fixup_16 + ((grub_uint16_t)((grub_uint32_t)adjust >> 16))); + break; + case GRUB_PE32_REL_BASED_LOW: + fixup_16 = (grub_uint16_t *)fixup; + *fixup_16 = (grub_uint16_t) (*fixup_16 + (grub_uint16_t)adjust); + break; + case GRUB_PE32_REL_BASED_HIGHLOW: + fixup_32 = (grub_uint32_t *)fixup; + *fixup_32 = *fixup_32 + (grub_uint32_t)adjust; + break; + case GRUB_PE32_REL_BASED_DIR64: + fixup_64 = (grub_uint64_t *)fixup; + *fixup_64 = *fixup_64 + (grub_uint64_t)adjust; + break; + default: + grub_error (GRUB_ERR_BAD_ARGUMENT, + "Reloc %d unknown relocation type %d", + n, (*entry) >> 12); + ret = GRUB_ERR_BAD_ARGUMENT; + goto out; + } + entry += 1; + } + reloc_base = (struct grub_pe32_data_directory *)reloc_end; + n++; + } + +out: + grub_free(reloc_buffer); + + return ret; +} + +grub_err_t +grub_multiboot2_load_pe (mbi_load_data_t *mld) +{ + int i; + grub_uint8_t *virt_addr; + grub_phys_addr_t phys_addr, reloc_base, reloc_base_end, base, end; + struct grub_pe32_section_table *reloc_section = NULL, fake_reloc_section; + struct grub_pe32_section_table *section; + grub_relocator_chunk_t ch; + pe_coff_loader_image_context_t context; + grub_err_t ret = GRUB_ERR_NONE; + grub_uint32_t section_alignment; + int found_entry_point = 0; + + ret = read_header(mld->buffer, MULTIBOOT_SEARCH, &context); + if (ret) + return ret; + + /* + * The spec says, uselessly, of SectionAlignment: + * ===== + * The alignment (in bytes) of sections when they are loaded into + * memory. It must be greater than or equal to FileAlignment. The + * default is the page size for the architecture. + * ===== + * Which doesn't tell you whose responsibility it is to enforce the + * "default", or when. It implies that the value in the field must + * be > FileAlignment (also poorly defined), but it appears visual + * studio will happily write 512 for FileAlignment (its default) and + * 0 for SectionAlignment, intending to imply PAGE_SIZE. + * + * We only support one page size, so if it's zero, nerf it to 4096. + */ + section_alignment = context.section_alignment; + if (section_alignment == 0) + section_alignment = 4096; + + section_alignment = grub_max(section_alignment, mld->align); + + ret = grub_relocator_alloc_chunk_align_safe (grub_multiboot2_relocator, &ch, + mld->min_addr, mld->max_addr, + context.image_size, section_alignment, + mld->preference, mld->avoid_efi_boot_services); + + if (ret) + { + grub_dprintf ("multiboot_loader", "Cannot allocate memory for OS image\n"); + return ret; + } + + virt_addr = get_virtual_current_address (ch); + phys_addr = get_physical_target_address (ch); + + if (grub_file_seek (mld->file, 0) == (grub_off_t) -1) { + ret = grub_errno; + goto out; + } + + if (grub_file_read (mld->file, virt_addr, context.size_of_headers) + != (grub_ssize_t) context.size_of_headers) + { + if (!grub_errno) + { + grub_error (GRUB_ERR_FILE_READ_ERROR, "premature end of file %s", + mld->filename); + ret = GRUB_ERR_FILE_READ_ERROR; + } + else + ret = grub_errno; + goto out; + } + + mld->load_base_addr = phys_addr; + mld->link_base_addr = context.image_address; + + grub_dprintf ("multiboot_loader", "load_base_addr: 0x%08x link_base_addr 0x%08x\n", + mld->load_base_addr, mld->link_base_addr); + + grub_multiboot2_payload_eip = context.entry_point; + grub_dprintf ("multiboot_loader", "entry_point: 0x%08x\n", grub_multiboot2_payload_eip); + if (!grub_multiboot2_payload_eip) + { + grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid entry point"); + ret = GRUB_ERR_BAD_ARGUMENT; + goto out; + } + + grub_dprintf ("multiboot_loader", "reloc_dir: %p reloc_size: 0x%08x\n", + (void *)(unsigned long)context.reloc_dir->rva, + context.reloc_dir->size); + reloc_base = image_address (phys_addr, context.image_size, + context.reloc_dir->rva); + /* RelocBaseEnd here is the address of the last byte of the table */ + reloc_base_end = image_address (phys_addr, context.image_size, + context.reloc_dir->rva + + context.reloc_dir->size - 1); + grub_dprintf ("multiboot_loader", "reloc_base: 0x%016lx reloc_base_end: 0x%016lx\n", + reloc_base, reloc_base_end); + + section = context.first_section; + for (i = 0; i < context.number_of_sections; i++, section++) + { + char name[9]; + + base = image_address (phys_addr, context.image_size, + section->virtual_address); + end = image_address (phys_addr, context.image_size, + section->virtual_address + section->virtual_size -1); + + grub_strncpy(name, section->name, 9); + name[8] = '\0'; + grub_dprintf ("multiboot_loader", "Section %d \"%s\" at 0x%016lx..0x%016lx\n", i, + name, base, end); + + if (end < base) + { + grub_dprintf ("multiboot_loader", " base is 0x%016lx but end is 0x%016lx... bad.\n", + base, end); + grub_error (GRUB_ERR_BAD_ARGUMENT, + "Image has invalid negative size"); + ret = GRUB_ERR_BAD_ARGUMENT; + goto out; + } + + if (section->virtual_address <= context.entry_point && + (section->virtual_address + section->raw_data_size - 1) + > context.entry_point) + { + found_entry_point++; + grub_dprintf ("multiboot_loader", " section contains entry point\n"); + } + + /* We do want to process .reloc, but it's often marked + * discardable, so we don't want to memcpy it. */ + if (grub_memcmp (section->name, ".reloc\0\0", 8) == 0) + { + if (reloc_section) + { + grub_error (GRUB_ERR_BAD_ARGUMENT, + "Image has multiple relocation sections"); + ret = GRUB_ERR_BAD_ARGUMENT; + goto out; + } + + /* If it has nonzero sizes, and our bounds check + * made sense, and the VA and size match RelocDir's + * versions, then we believe in this section table. */ + if (section->raw_data_size && section->virtual_size && + base && end && reloc_base == base) + { + if (reloc_base_end == end) + { + grub_dprintf ("multiboot_loader", " section is relocation section\n"); + reloc_section = section; + } + else if (reloc_base_end && reloc_base_end < end) + { + /* Bogus virtual size in the reloc section -- RelocDir + * reported a smaller Base Relocation Directory. Decrease + * the section's virtual size so that it equal RelocDir's + * idea, but only for the purposes of relocate_coff(). */ + grub_dprintf ("multiboot_loader", + " section is (overlong) relocation section\n"); + grub_memcpy (&fake_reloc_section, section, sizeof *section); + fake_reloc_section.virtual_size -= (end - reloc_base_end); + reloc_section = &fake_reloc_section; + } + } + + if (!reloc_section) + { + grub_dprintf ("multiboot_loader", " section is not reloc section?\n"); + grub_dprintf ("multiboot_loader", " rds: 0x%08x, vs: %08x\n", + section->raw_data_size, section->virtual_size); + grub_dprintf ("multiboot_loader", " base: 0x%016lx end: 0x%016lx\n", base, end); + grub_dprintf ("multiboot_loader", " reloc_base: 0x%016lx reloc_base_end: 0x%016lx\n", + reloc_base, reloc_base_end); + } + } + + grub_dprintf ("multiboot_loader", " Section characteristics are %08x\n", + section->characteristics); + grub_dprintf ("multiboot_loader", " Section virtual size: %08x\n", + section->virtual_size); + grub_dprintf ("multiboot_loader", " Section raw_data size: %08x\n", + section->raw_data_size); + if (section->characteristics & GRUB_PE32_SCN_MEM_DISCARDABLE) + { + grub_dprintf ("multiboot_loader", " Discarding section\n"); + continue; + } + + if (!base || !end) + { + grub_dprintf ("multiboot_loader", " section is invalid\n"); + grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid section size"); + ret = GRUB_ERR_BAD_ARGUMENT; + goto out; + } + + if (section->characteristics & GRUB_PE32_SCN_CNT_UNINITIALIZED_DATA) + { + if (section->raw_data_size != 0) + grub_dprintf ("multiboot_loader", " UNINITIALIZED_DATA section has data?\n"); + } + else if (section->virtual_address < context.size_of_headers || + section->raw_data_offset < context.size_of_headers) + { + grub_error (GRUB_ERR_BAD_ARGUMENT, + "Section %d is inside image headers", i); + ret = GRUB_ERR_BAD_ARGUMENT; + goto out; + } + + if (section->raw_data_size > 0) + { + grub_dprintf ("multiboot_loader", " copying 0x%08x bytes to 0x%016lx\n", + section->raw_data_size, base); + + if (grub_file_seek (mld->file, section->raw_data_offset) == (grub_off_t) -1) + { + ret = grub_errno; + goto out; + } + + if (grub_file_read (mld->file, virt_addr + (base - phys_addr), section->raw_data_size) + != (grub_ssize_t) section->raw_data_size) + { + if (!grub_errno) + { + grub_error (GRUB_ERR_FILE_READ_ERROR, "premature end of file %s", + mld->filename); + ret = GRUB_ERR_FILE_READ_ERROR; + } + else + ret = grub_errno; + goto out; + } + } + + if (section->raw_data_size < section->virtual_size) + { + grub_dprintf ("multiboot_loader", " padding with 0x%08x bytes at 0x%016lx\n", + section->virtual_size - section->raw_data_size, + base + section->raw_data_size); + grub_memset (virt_addr + (base - phys_addr) + section->raw_data_size, 0, + section->virtual_size - section->raw_data_size); + } + + grub_dprintf ("multiboot_loader", " finished section %s\n", name); + } + + /* 5 == EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC */ + if (context.number_of_rva_and_sizes <= 5) + { + grub_error (GRUB_ERR_BAD_ARGUMENT, "image has no relocation entry\n"); + ret = GRUB_ERR_BAD_ARGUMENT; + goto out; + } + + if (context.reloc_dir->size && reloc_section) + { + /* run the relocation fixups */ + ret = relocate_coff (&context, reloc_section, phys_addr, virt_addr, mld); + + if (ret) + { + grub_error (GRUB_ERR_BAD_ARGUMENT, "relocation failed"); + goto out; + } + } + + if (!found_entry_point) + { + grub_error (GRUB_ERR_BAD_ARGUMENT, "entry point is not within sections"); + ret = GRUB_ERR_BAD_ARGUMENT; + goto out; + } + if (found_entry_point > 1) + { + grub_error (GRUB_ERR_BAD_ARGUMENT, "%d sections contain entry point", + found_entry_point); + ret = GRUB_ERR_BAD_ARGUMENT; + goto out; + } + +out: + return ret; +} diff --git a/include/grub/efi/pe32.h b/include/grub/efi/pe32.h index 4e6e9d254bd3..94435d758b46 100644 --- a/include/grub/efi/pe32.h +++ b/include/grub/efi/pe32.h @@ -20,6 +20,7 @@ #define GRUB_EFI_PE32_HEADER 1 #include +#include #include /* The MSDOS compatibility stub. This was copied from the output of @@ -46,6 +47,28 @@ #define GRUB_PE32_MSDOS_STUB_SIZE 0x80 +typedef struct { + grub_uint16_t e_magic; ///< Magic number. + grub_uint16_t e_cblp; ///< Bytes on last page of file. + grub_uint16_t e_cp; ///< Pages in file. + grub_uint16_t e_crlc; ///< Relocations. + grub_uint16_t e_cparhdr; ///< Size of header in paragraphs. + grub_uint16_t e_minalloc; ///< Minimum extra paragraphs needed. + grub_uint16_t e_maxalloc; ///< Maximum extra paragraphs needed. + grub_uint16_t e_ss; ///< Initial (relative) SS value. + grub_uint16_t e_sp; ///< Initial SP value. + grub_uint16_t e_csum; ///< Checksum. + grub_uint16_t e_ip; ///< Initial IP value. + grub_uint16_t e_cs; ///< Initial (relative) CS value. + grub_uint16_t e_lfarlc; ///< File address of relocation table. + grub_uint16_t e_ovno; ///< Overlay number. + grub_uint16_t e_res[4]; ///< Reserved words. + grub_uint16_t e_oemid; ///< OEM identifier (for e_oeminfo). + grub_uint16_t e_oeminfo; ///< OEM information; e_oemid specific. + grub_uint16_t e_res2[10]; ///< Reserved words. + grub_uint32_t e_lfanew; ///< File address of new exe header. +} grub_pe32_msdos_header_t; + #define GRUB_PE32_MAGIC 0x5a4d struct grub_msdos_image_header @@ -249,6 +272,7 @@ struct grub_pe32_section_table #define GRUB_PE32_SCN_CNT_CODE 0x00000020 #define GRUB_PE32_SCN_CNT_INITIALIZED_DATA 0x00000040 +#define GRUB_PE32_SCN_CNT_UNINITIALIZED_DATA 0x00000080 #define GRUB_PE32_SCN_MEM_DISCARDABLE 0x02000000 #define GRUB_PE32_SCN_MEM_EXECUTE 0x20000000 #define GRUB_PE32_SCN_MEM_READ 0x40000000 @@ -349,4 +373,44 @@ struct grub_pe32_reloc #define GRUB_PE32_REL_I386_DIR32 0x6 #define GRUB_PE32_REL_I386_REL32 0x14 +struct grub_pe32_header_32 +{ + char signature[GRUB_PE32_SIGNATURE_SIZE]; + struct grub_pe32_coff_header coff_header; + struct grub_pe32_optional_header optional_header; +}; + +struct grub_pe32_header_64 +{ + char signature[GRUB_PE32_SIGNATURE_SIZE]; + struct grub_pe32_coff_header coff_header; + struct grub_pe64_optional_header optional_header; +}; + +typedef union +{ + struct grub_pe32_header_32 pe32; + struct grub_pe32_header_64 pe32plus; +} grub_pe_header_t; + +struct pe_coff_loader_image_context +{ + grub_efi_uint64_t image_address; + grub_efi_uint64_t image_size; + grub_efi_uint64_t entry_point; + grub_efi_uintn_t size_of_headers; + grub_efi_uint16_t image_type; + grub_efi_uint16_t number_of_sections; + grub_efi_uint32_t section_alignment; + struct grub_pe32_section_table *first_section; + struct grub_pe32_data_directory *reloc_dir; + struct grub_pe32_data_directory *sec_dir; + grub_efi_uint64_t number_of_rva_and_sizes; + grub_pe_header_t *pe_hdr; +}; + +typedef struct pe_coff_loader_image_context pe_coff_loader_image_context_t; + +#define EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES 16 + #endif /* ! GRUB_EFI_PE32_HEADER */ diff --git a/include/grub/multiboot2.h b/include/grub/multiboot2.h index 1f6d4fc9e336..01e2b11755c2 100644 --- a/include/grub/multiboot2.h +++ b/include/grub/multiboot2.h @@ -97,6 +97,9 @@ typedef struct mbi_load_data mbi_load_data_t; grub_err_t grub_multiboot2_load_elf (mbi_load_data_t *mld); +grub_err_t +grub_multiboot2_load_pe (mbi_load_data_t *mld); + extern grub_size_t grub_multiboot2_pure_size; extern grub_size_t grub_multiboot2_alloc_mbi; extern grub_uint32_t grub_multiboot2_payload_eip; From patchwork Wed Mar 13 15:07:46 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ross Lagerwall X-Patchwork-Id: 13591493 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 37E93C54E66 for ; Wed, 13 Mar 2024 15:06:59 +0000 (UTC) Received: from list by lists.xenproject.org with outflank-mailman.692520.1079768 (Exim 4.92) (envelope-from ) id 1rkQBu-0008IG-OH; Wed, 13 Mar 2024 15:06:50 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version Received: by outflank-mailman (output) from mailman id 692520.1079768; Wed, 13 Mar 2024 15:06:50 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1rkQBu-0008I9-LM; Wed, 13 Mar 2024 15:06:50 +0000 Received: by outflank-mailman (input) for mailman id 692520; Wed, 13 Mar 2024 15:06:48 +0000 Received: from se1-gles-sth1-in.inumbo.com ([159.253.27.254] helo=se1-gles-sth1.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1rkQBs-0007DJ-Nd for xen-devel@lists.xenproject.org; Wed, 13 Mar 2024 15:06:48 +0000 Received: from mail-qv1-xf2a.google.com (mail-qv1-xf2a.google.com [2607:f8b0:4864:20::f2a]) by se1-gles-sth1.inumbo.com (Halon) with ESMTPS id 4fe8adc5-e14b-11ee-afdd-a90da7624cb6; Wed, 13 Mar 2024 16:06:48 +0100 (CET) Received: by mail-qv1-xf2a.google.com with SMTP id 6a1803df08f44-68f571be9ddso53971826d6.0 for ; Wed, 13 Mar 2024 08:06:48 -0700 (PDT) Received: from rossla-lxenia.eng.citrite.net ([185.25.67.249]) by smtp.gmail.com with ESMTPSA id p10-20020a0ccb8a000000b0068fba49ae81sm4786811qvk.57.2024.03.13.08.06.45 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 13 Mar 2024 08:06:46 -0700 (PDT) X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" X-Inumbo-ID: 4fe8adc5-e14b-11ee-afdd-a90da7624cb6 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=citrix.com; s=google; t=1710342407; x=1710947207; darn=lists.xenproject.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=kpYcDsI+M6briD4qjQYG+D2zD6DLXgwh1H3IqVNt/RM=; b=BigxsrG+Ozj/kCSgpXM618RVYXFnWY37FCTmX1rXMFaDaS9Gm6AcZelBo9XkcLeAoa OVo3ypZCETcE72FJj1Js7GIGEOzDeRxREu17g1ETpOAu/nfKJqc97cXRmIozwglJJpAL dgKvMoZGJuaHZ07hgn0Swjbk6X3yV47bZGAhU= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1710342407; x=1710947207; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=kpYcDsI+M6briD4qjQYG+D2zD6DLXgwh1H3IqVNt/RM=; b=VIlr6mgxi1bC8ieDt658BXXQc4AmO6CEtof3yUl8ADexNKdgW1pq49aSznyfz18xa7 i6rtsh0lRqvTstxjd906XLLSR0BvoYgTA5q7rQW7WGW1yuXj13ncavMZ50S0b1JQGcbi KUrSTkzmQDbF/j2Ypwb3Ddpg6CUtXfwBAJ+BT0IEEpMH5ZNeGwSQSDLvVMYbvK4WVvoc LX8+1nwS1MS8kU8Ep8nfyCyOrsDc2ZdyJB9CGHBOcTQy7Qu+lvKiDxZB4R5XTsujKv7f dycSbAiogRMGfG8AqcRGdUHfg2X3/g/lRtcce1HjcQKyYvbOwRs9GkWKFg1ac0QHpyji bg+Q== X-Gm-Message-State: AOJu0Ywp5fWlXTtcoliZse0YW2z3vf4bYBW1Sq+YiuqUku82cL/daqHb go83p/b1YSjZQx9lo9Sf2cmE0XdbopLqciGXlb8AcS5yTZhQukmNDLrvMjSVaw== X-Google-Smtp-Source: AGHT+IFKcbExg32xHCfDC0TqWfQFSuyDOMhILY/iB+QL677shqOJeZILRaYMT4dW0UohQCma6B2uYQ== X-Received: by 2002:ad4:4bad:0:b0:690:cb91:80d9 with SMTP id i13-20020ad44bad000000b00690cb9180d9mr90900qvw.48.1710342407050; Wed, 13 Mar 2024 08:06:47 -0700 (PDT) From: Ross Lagerwall To: grub-devel@gnu.org Cc: xen-devel@lists.xenproject.org, Andrew Cooper , Daniel Kiper , Ross Lagerwall Subject: [PATCH 5/7] multiboot2: Add support for 64-bit entry addresses Date: Wed, 13 Mar 2024 15:07:46 +0000 Message-ID: <20240313150748.791236-6-ross.lagerwall@citrix.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240313150748.791236-1-ross.lagerwall@citrix.com> References: <20240313150748.791236-1-ross.lagerwall@citrix.com> MIME-Version: 1.0 Add support for entry addresses that may be either 32 bits or 64 bits in size. This may be necessary if the binary is built with an entry address above 4G. Signed-off-by: Ross Lagerwall --- grub-core/loader/multiboot_mbi2.c | 10 ++++++++-- include/multiboot2.h | 6 +++++- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/grub-core/loader/multiboot_mbi2.c b/grub-core/loader/multiboot_mbi2.c index 3ec96e2f29b9..c268aa614284 100644 --- a/grub-core/loader/multiboot_mbi2.c +++ b/grub-core/loader/multiboot_mbi2.c @@ -205,13 +205,19 @@ grub_multiboot2_load (grub_file_t file, const char *filename) case MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS: entry_specified = 1; - entry = ((struct multiboot_header_tag_entry_address *) tag)->entry_addr; + if ((tag->size - sizeof(struct multiboot_header_tag)) == sizeof(multiboot_uint64_t)) + entry = ((struct multiboot_header_tag_entry_address *) tag)->entry_addr64; + else + entry = ((struct multiboot_header_tag_entry_address *) tag)->entry_addr32; break; case MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI64: #if defined (GRUB_MACHINE_EFI) && defined (__x86_64__) efi_entry_specified = 1; - efi_entry = ((struct multiboot_header_tag_entry_address *) tag)->entry_addr; + if ((tag->size - sizeof(struct multiboot_header_tag)) == sizeof(multiboot_uint64_t)) + efi_entry = ((struct multiboot_header_tag_entry_address *) tag)->entry_addr64; + else + efi_entry = ((struct multiboot_header_tag_entry_address *) tag)->entry_addr32; #endif break; diff --git a/include/multiboot2.h b/include/multiboot2.h index f4377bf7b394..e4798bfef937 100644 --- a/include/multiboot2.h +++ b/include/multiboot2.h @@ -140,7 +140,11 @@ struct multiboot_header_tag_entry_address multiboot_uint16_t type; multiboot_uint16_t flags; multiboot_uint32_t size; - multiboot_uint32_t entry_addr; + union + { + multiboot_uint32_t entry_addr32; + multiboot_uint64_t entry_addr64; + }; }; struct multiboot_header_tag_console_flags From patchwork Wed Mar 13 15:07:47 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ross Lagerwall X-Patchwork-Id: 13591494 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 3D278C54E68 for ; Wed, 13 Mar 2024 15:07:00 +0000 (UTC) Received: from list by lists.xenproject.org with outflank-mailman.692522.1079789 (Exim 4.92) (envelope-from ) id 1rkQBw-0000Oy-PX; Wed, 13 Mar 2024 15:06:52 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version Received: by outflank-mailman (output) from mailman id 692522.1079789; Wed, 13 Mar 2024 15:06:52 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1rkQBw-0000Nr-JH; Wed, 13 Mar 2024 15:06:52 +0000 Received: by outflank-mailman (input) for mailman id 692522; Wed, 13 Mar 2024 15:06:51 +0000 Received: from se1-gles-flk1-in.inumbo.com ([94.247.172.50] helo=se1-gles-flk1.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1rkQBv-0007E2-IA for xen-devel@lists.xenproject.org; Wed, 13 Mar 2024 15:06:51 +0000 Received: from mail-qv1-xf2d.google.com (mail-qv1-xf2d.google.com [2607:f8b0:4864:20::f2d]) by se1-gles-flk1.inumbo.com (Halon) with ESMTPS id 51169e27-e14b-11ee-a1ee-f123f15fe8a2; Wed, 13 Mar 2024 16:06:50 +0100 (CET) Received: by mail-qv1-xf2d.google.com with SMTP id 6a1803df08f44-690cd7f83cdso8532866d6.3 for ; Wed, 13 Mar 2024 08:06:50 -0700 (PDT) Received: from rossla-lxenia.eng.citrite.net ([185.25.67.249]) by smtp.gmail.com with ESMTPSA id p10-20020a0ccb8a000000b0068fba49ae81sm4786811qvk.57.2024.03.13.08.06.47 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 13 Mar 2024 08:06:48 -0700 (PDT) X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" X-Inumbo-ID: 51169e27-e14b-11ee-a1ee-f123f15fe8a2 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=citrix.com; s=google; t=1710342409; x=1710947209; darn=lists.xenproject.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=U2qmXAF7kH+Xo7dcYPNWV07zKXcD5akVAYdTNUPm5Ak=; b=tVB1GiHpXnQcD2V5b25BTuVUuKyMOyyTq4RDppna8VBmkXhb3uXtaysPMNa+YrYxG4 dN7nhhA0RMx+epSBl4Djp4B3fbe0cinqAxEPzXvk5n2sA0m2tScKNd0DhagRCptSa7ou y2OkTda3cC934cNnUfR+fJLROfrvg4jW0sLk8= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1710342409; x=1710947209; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=U2qmXAF7kH+Xo7dcYPNWV07zKXcD5akVAYdTNUPm5Ak=; b=FHzoKKNIVhhMb01MeZEFn3BF1DpW4qNyd36xNQLQB922CMmjm0/ISN+HxmBEIVeM1M gXE5Nn/qV1yFVmG/zPhjVQKrXJY9He6MWZDtm8u98Vs9YJB5Dae201G+BxvD7rKkBVk8 dS6EapDPd+Ok4sOtFuzFjvagL6zegya+8m0kFxFswTH2F3Q4fGSDvrbUWOxyM1ewwVun qMXcAHjTID3uTdqdG/pMZ2kV7xSAqHKIq83HiRO05ZtdXd3Kt9j2+MgPOtUACL+dB7+n AFj4mDDYC0pxYQ0eI+gjzauof3/u65pSKI0Pj30dwYeJWVvRqUnJdNJaTewAeS4Q7MFJ yGrg== X-Gm-Message-State: AOJu0Yz4PIbcoiXHPm8cpWVhDdkg2GdepPEODpLiDUw6HC+aa5CZAuLK YnKwCB57v0v9oFwfyq3Txolquvr0s7KESxj2ymKjkhGe0Wv5wZprjkdPXPUHpw== X-Google-Smtp-Source: AGHT+IGQZ+RUgmwNMglkrjL/bMqOBHmzI4m56/rX8h6MM0HjI4O+cM+TZ42/QjkUrbzW3oCnXKu05Q== X-Received: by 2002:ad4:4e14:0:b0:690:b40b:8084 with SMTP id dl20-20020ad44e14000000b00690b40b8084mr74464qvb.40.1710342408924; Wed, 13 Mar 2024 08:06:48 -0700 (PDT) From: Ross Lagerwall To: grub-devel@gnu.org Cc: xen-devel@lists.xenproject.org, Andrew Cooper , Daniel Kiper , Ross Lagerwall Subject: [PATCH 6/7] efi: Allow loading multiboot modules without verification Date: Wed, 13 Mar 2024 15:07:47 +0000 Message-ID: <20240313150748.791236-7-ross.lagerwall@citrix.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240313150748.791236-1-ross.lagerwall@citrix.com> References: <20240313150748.791236-1-ross.lagerwall@citrix.com> MIME-Version: 1.0 GRUB doesn't do anything with multiboot modules except loading them and passing a pointer to the multiboot kernel. Therefore GRUB itself doesn't need to verify the module. Multiboot modules may contain code that needs to be verified. If this is the case, the expectation is that the multiboot kernel verifies the modules. For example, with Xen, the first multiboot module contains the dom0 kernel binary and Xen verifies it before starting it. Signed-off-by: Ross Lagerwall --- grub-core/kern/efi/sb.c | 1 + 1 file changed, 1 insertion(+) diff --git a/grub-core/kern/efi/sb.c b/grub-core/kern/efi/sb.c index 8d3e413608bb..f76290d65e9f 100644 --- a/grub-core/kern/efi/sb.c +++ b/grub-core/kern/efi/sb.c @@ -171,6 +171,7 @@ shim_lock_verifier_init (grub_file_t io __attribute__ ((unused)), case GRUB_FILE_TYPE_LOADENV: case GRUB_FILE_TYPE_SAVEENV: case GRUB_FILE_TYPE_VERIFY_SIGNATURE: + case GRUB_FILE_TYPE_MULTIBOOT_MODULE: *flags = GRUB_VERIFY_FLAGS_SKIP_VERIFICATION; return GRUB_ERR_NONE; From patchwork Wed Mar 13 15:07:48 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ross Lagerwall X-Patchwork-Id: 13591496 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 88193C54E66 for ; Wed, 13 Mar 2024 15:07:03 +0000 (UTC) Received: from list by lists.xenproject.org with outflank-mailman.692523.1079799 (Exim 4.92) (envelope-from ) id 1rkQBy-0000jy-Vg; Wed, 13 Mar 2024 15:06:54 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version Received: by outflank-mailman (output) from mailman id 692523.1079799; Wed, 13 Mar 2024 15:06:54 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1rkQBy-0000jl-SP; Wed, 13 Mar 2024 15:06:54 +0000 Received: by outflank-mailman (input) for mailman id 692523; Wed, 13 Mar 2024 15:06:53 +0000 Received: from se1-gles-flk1-in.inumbo.com ([94.247.172.50] helo=se1-gles-flk1.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1rkQBx-0007E2-1i for xen-devel@lists.xenproject.org; Wed, 13 Mar 2024 15:06:53 +0000 Received: from mail-qv1-xf2e.google.com (mail-qv1-xf2e.google.com [2607:f8b0:4864:20::f2e]) by se1-gles-flk1.inumbo.com (Halon) with ESMTPS id 51f6b447-e14b-11ee-a1ee-f123f15fe8a2; Wed, 13 Mar 2024 16:06:51 +0100 (CET) Received: by mail-qv1-xf2e.google.com with SMTP id 6a1803df08f44-690cbf99143so21178816d6.3 for ; Wed, 13 Mar 2024 08:06:51 -0700 (PDT) Received: from rossla-lxenia.eng.citrite.net ([185.25.67.249]) by smtp.gmail.com with ESMTPSA id p10-20020a0ccb8a000000b0068fba49ae81sm4786811qvk.57.2024.03.13.08.06.49 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 13 Mar 2024 08:06:49 -0700 (PDT) X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" X-Inumbo-ID: 51f6b447-e14b-11ee-a1ee-f123f15fe8a2 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=citrix.com; s=google; t=1710342410; x=1710947210; darn=lists.xenproject.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=uqR8dKNf2s+DB1oba15Jm7Zlu18CJES9pn/IS/ryqIY=; b=hKMWjp32zbDDbRUzLQVOmaD7ECertCm6lXOmmi6FBOwsQHJRYypJmcIPkAMjIYGyy/ 6Qs/+ULmuo0S5fapTQASWavQ7rE8RmRHueuOZkr9uEqtn5JXndvMhUMTsVUV9yvR8Itk 2hdSELXFheaQCwpOlpc4fKNIOr5xyKF6uIB+8= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1710342410; x=1710947210; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=uqR8dKNf2s+DB1oba15Jm7Zlu18CJES9pn/IS/ryqIY=; b=u7fm9E7mREUAZ9YfcQbtk+EcecKg2wBi944YxPDdpRr3PP9WZhQzu66AUmrBCmYeFf VOiRw9mCaX54D2itcqdv90DhVz/mmMoqzlphdQuftyD5yj6j0v3hef5oHjziE+2RzMDB moEP8zHiIIWK3xQZ16baj9yxS0wljX53FzBh3mXfJfFhwW4E0kJQLMWAtCZmLrrcl4ur zx0WywoNMILlJiZ36G2VcV2IIT2PU7ERDcHWfpdKGybPF9C1O3up6VJBEbsOg0zp7184 Wt5V8wGIOiCIUpHo3Jkl5VFfuhbT02Y0RXPTujCaYYOxDEf6x+xLD2dljid5RocrjNJv IlhA== X-Gm-Message-State: AOJu0YyCp+yFzFXHqbCVmgNvEJIJ6Kmlbbi+ljcSyZXEUSduYGFKOxQe rIh2foQKetdBTqEfTXjY0xea9VmS7032fnGFGoiRUNSbHrQ6vt9vgR2/Pjq5GQ== X-Google-Smtp-Source: AGHT+IHxT3dfA7sDvc0ZsxxYeT08+PpGu6wmIj3vwZ/i++W2G2MrBTw/4jrp+2lKPO2k1A6hnNmZVQ== X-Received: by 2002:a0c:ea43:0:b0:690:df46:3949 with SMTP id u3-20020a0cea43000000b00690df463949mr116341qvp.35.1710342410458; Wed, 13 Mar 2024 08:06:50 -0700 (PDT) From: Ross Lagerwall To: grub-devel@gnu.org Cc: xen-devel@lists.xenproject.org, Andrew Cooper , Daniel Kiper , Ross Lagerwall Subject: [PATCH 7/7] verifiers: Verify after decompression Date: Wed, 13 Mar 2024 15:07:48 +0000 Message-ID: <20240313150748.791236-8-ross.lagerwall@citrix.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240313150748.791236-1-ross.lagerwall@citrix.com> References: <20240313150748.791236-1-ross.lagerwall@citrix.com> MIME-Version: 1.0 It is convenient and common to have binaries stored in gzip archives (e.g. xen.gz). Verification should be run after decompression rather than before so reorder the file filter list as appropriate. Signed-off-by: Ross Lagerwall --- include/grub/file.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/grub/file.h b/include/grub/file.h index a5bf3a792d6f..a1ef3582bc7b 100644 --- a/include/grub/file.h +++ b/include/grub/file.h @@ -182,10 +182,10 @@ extern grub_disk_read_hook_t EXPORT_VAR(grub_file_progress_hook); /* Filters with lower ID are executed first. */ typedef enum grub_file_filter_id { - GRUB_FILE_FILTER_VERIFY, GRUB_FILE_FILTER_GZIO, GRUB_FILE_FILTER_XZIO, GRUB_FILE_FILTER_LZOPIO, + GRUB_FILE_FILTER_VERIFY, GRUB_FILE_FILTER_MAX, GRUB_FILE_FILTER_COMPRESSION_FIRST = GRUB_FILE_FILTER_GZIO, GRUB_FILE_FILTER_COMPRESSION_LAST = GRUB_FILE_FILTER_LZOPIO,