diff mbox series

[2/7] multiboot2: Allow 64-bit entry tags

Message ID 20240313150748.791236-3-ross.lagerwall@citrix.com (mailing list archive)
State New, archived
Headers show
Series GRUB: Supporting Secure Boot of xen.gz | expand

Commit Message

Ross Lagerwall March 13, 2024, 3:07 p.m. UTC
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 <ross.lagerwall@citrix.com>
---
 doc/multiboot.texi | 32 +++++++++++++++++++-------------
 doc/multiboot2.h   |  6 +++++-
 2 files changed, 24 insertions(+), 14 deletions(-)

Comments

Roger Pau Monné March 19, 2024, 10:07 a.m. UTC | #1
On Wed, Mar 13, 2024 at 03:07:43PM +0000, Ross Lagerwall wrote:
> 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 <ross.lagerwall@citrix.com>
> ---
>  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        |
> +          +-------------------+

I might be confused, but this entry point is used in 32bit protected
mode, and hence a 64bit value is simply impossible to use according to
the protocol in "3.3 I386 machine state".

Unless that section is expanded to describe other protocols that use
the entry address in a way where 64bits could be meaningful it seems
pointless to expand the field.

>  @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        |
> +          +-------------------+

This does seem sensible.

Thanks, Roger.
Ross Lagerwall March 28, 2024, 3:05 p.m. UTC | #2
On Tue, Mar 19, 2024 at 10:07 AM Roger Pau Monné <roger.pau@citrix.com> wrote:
>
> On Wed, Mar 13, 2024 at 03:07:43PM +0000, Ross Lagerwall wrote:
> > 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 <ross.lagerwall@citrix.com>
> > ---
> >  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        |
> > +          +-------------------+
>
> I might be confused, but this entry point is used in 32bit protected
> mode, and hence a 64bit value is simply impossible to use according to
> the protocol in "3.3 I386 machine state".
>
> Unless that section is expanded to describe other protocols that use
> the entry address in a way where 64bits could be meaningful it seems
> pointless to expand the field.

I changed this because the same binary is being used for both BIOS boot
and UEFI boot, therefore it may have a base address above 4 GiB.
Despite that, it is expected that GRUB would relocate the binary below
4 GiB so BIOS boot would still work.

However, on reflection this is kind of nasty. I've managed to build Xen
in such a way that this is no longer needed so I can drop this change
from the next version of this series.

Ross
Roger Pau Monné March 28, 2024, 3:41 p.m. UTC | #3
On Thu, Mar 28, 2024 at 03:05:47PM +0000, Ross Lagerwall wrote:
> On Tue, Mar 19, 2024 at 10:07 AM Roger Pau Monné <roger.pau@citrix.com> wrote:
> >
> > On Wed, Mar 13, 2024 at 03:07:43PM +0000, Ross Lagerwall wrote:
> > > 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 <ross.lagerwall@citrix.com>
> > > ---
> > >  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        |
> > > +          +-------------------+
> >
> > I might be confused, but this entry point is used in 32bit protected
> > mode, and hence a 64bit value is simply impossible to use according to
> > the protocol in "3.3 I386 machine state".
> >
> > Unless that section is expanded to describe other protocols that use
> > the entry address in a way where 64bits could be meaningful it seems
> > pointless to expand the field.
> 
> I changed this because the same binary is being used for both BIOS boot
> and UEFI boot, therefore it may have a base address above 4 GiB.
> Despite that, it is expected that GRUB would relocate the binary below
> 4 GiB so BIOS boot would still work.

Right, for UEFI boot it's possible to have entry addresses above 4GB,
because the entry point is called in long mode with identity page
tables (and hence you can put addresses in %rip past the 4GB
boundary).

However the multiboot entry point puts the CPU in 32bit protected
mode, and hence %eip can only hold a value below the 4GB boundary.

It's technically impossible to use an entry point above 4GB, unless
there's something that I'm missing that changes the initial CPU state
for the multiboot2 entry point.

Thanks, Roger.
diff mbox series

Patch

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