Re: [Xen-devel] [GRUB2 PATCH v5 4/4] multiboot2: Add support for relocatable images

2016-03-25 Thread Konrad Rzeszutek Wilk
On Fri, Mar 18, 2016 at 06:00:27PM +0100, Daniel Kiper wrote:
> Currently multiboot2 protocol loads image exactly at address specified in
> ELF or multiboot2 header. This solution works quite well on legacy BIOS
> platforms. It is possible because memory regions are placed at predictable
> addresses (though I was not able to find any spec which says that it is
> strong requirement, so, it looks that it is just a goodwill of hardware
> designers). However, EFI platforms are more volatile. Even if required
> memory regions live at specific addresses then they are sometimes simply
> not free (e.g. used by boot/runtime services on Dell PowerEdge R820 and
> OVMF). This means that you are not able to just set up final image
> destination on build time. You have to provide method to relocate image
> contents to real load address which is usually different than load address
> specified in ELF and multiboot2 headers.
> 
> This patch provides all needed machinery to do self relocation in image code.
> First of all GRUB2 reads min_addr (min. load addr), max_addr (max. load addr),
> align (required image alignment), preference (it says which memory regions are
> preferred by image, e.g. none, low, high) from 
> multiboot_header_tag_relocatable
> header tag contained in binary (at this stage load addresses from multiboot2
> and/or ELF headers are ignored). Later loader tries to fulfill request (not 
> only
> that one) and if it succeeds then it informs image about real load address via
> multiboot_tag_load_base_addr tag. At this stage GRUB2 role is finished. 
> Starting
> from now executable must cope with relocations itself using whole static and
> dynamic knowledge provided by boot loader.
> 
> This patch does not provide functionality which could do relocations using
> ELF relocation data. However, I was asked by Konrad Rzeszutek Wilk and 
> Vladimir
> 'phcoder' Serbinenko to investigate that thing. It looks that relevant 
> machinery
> could be added to existing code (including this patch) without huge effort.
> Additionally, ELF relocation could live in parallel with self relocation 
> provided
> by this patch. However, during research I realized that first of all we should
> establish the details how ELF relocatable image should look like and how it 
> should
> be build. At least to build proper test/example files.
> 
> So, this patch just provides support for self relocatable images. If ELF file
> with relocs is loaded then GRUB2 complains loudly and ignores it. Support for
> such files will be added later.
> 
> This patch was tested with Xen image which uses that functionality. However, 
> this Xen
> feature is still under development and new patchset will be released in about 
> 3-4 weeks.

> index e3a39b6..8a9ab0c 100644
> --- a/grub-core/loader/multiboot_elfxx.c
> +++ b/grub-core/loader/multiboot_elfxx.c

..snip..
>  static grub_err_t
> -CONCAT(grub_multiboot_load_elf, XX) (grub_file_t file, const char *filename, 
> void *buffer)
> +CONCAT(grub_multiboot_load_elf, XX) (mbi_load_data_t *mld)
>  {
> +#ifdef MULTIBOOT_LOAD_ELF64
> +  if (highest_load >= 0x1)
> +return grub_error (GRUB_ERR_BAD_OS, "segment cross 4 GiB border");

segment crosses 4GiB border!

___
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel


[Xen-devel] [GRUB2 PATCH v5 4/4] multiboot2: Add support for relocatable images

2016-03-19 Thread Daniel Kiper
Currently multiboot2 protocol loads image exactly at address specified in
ELF or multiboot2 header. This solution works quite well on legacy BIOS
platforms. It is possible because memory regions are placed at predictable
addresses (though I was not able to find any spec which says that it is
strong requirement, so, it looks that it is just a goodwill of hardware
designers). However, EFI platforms are more volatile. Even if required
memory regions live at specific addresses then they are sometimes simply
not free (e.g. used by boot/runtime services on Dell PowerEdge R820 and
OVMF). This means that you are not able to just set up final image
destination on build time. You have to provide method to relocate image
contents to real load address which is usually different than load address
specified in ELF and multiboot2 headers.

This patch provides all needed machinery to do self relocation in image code.
First of all GRUB2 reads min_addr (min. load addr), max_addr (max. load addr),
align (required image alignment), preference (it says which memory regions are
preferred by image, e.g. none, low, high) from multiboot_header_tag_relocatable
header tag contained in binary (at this stage load addresses from multiboot2
and/or ELF headers are ignored). Later loader tries to fulfill request (not only
that one) and if it succeeds then it informs image about real load address via
multiboot_tag_load_base_addr tag. At this stage GRUB2 role is finished. Starting
from now executable must cope with relocations itself using whole static and
dynamic knowledge provided by boot loader.

This patch does not provide functionality which could do relocations using
ELF relocation data. However, I was asked by Konrad Rzeszutek Wilk and Vladimir
'phcoder' Serbinenko to investigate that thing. It looks that relevant machinery
could be added to existing code (including this patch) without huge effort.
Additionally, ELF relocation could live in parallel with self relocation 
provided
by this patch. However, during research I realized that first of all we should
establish the details how ELF relocatable image should look like and how it 
should
be build. At least to build proper test/example files.

So, this patch just provides support for self relocatable images. If ELF file
with relocs is loaded then GRUB2 complains loudly and ignores it. Support for
such files will be added later.

This patch was tested with Xen image which uses that functionality. However, 
this Xen
feature is still under development and new patchset will be released in about 
3-4 weeks.

Signed-off-by: Daniel Kiper 
---
v5 - suggestions/fixes:
   - fix support for multi segment ELF files
 (suggested by Vladimir 'phcoder' Serbinenko),
   - add some input data checks,
   - add some comments.

v4 - suggestions/fixes:
   - pack grub_multiboot_load_elf() arguments into struct
 (suggested by Juergen Gross, Konrad Rzeszutek Wilk
 and Vladimir 'phcoder' Serbinenko),
   - fix entry point address calculation
 (suggested by Vladimir 'phcoder' Serbinenko),
   - fail if ELF file has relocs sections
 (suggested by Vladimir 'phcoder' Serbinenko).

v3 - suggestions/fixes:
   - reduce number of casts
 (suggested by Konrad Rzeszutek Wilk),
   - remove unneeded space at the end of line
 (suggested by Konrad Rzeszutek Wilk),
   - improve commit message
 (suggested by Konrad Rzeszutek Wilk).
---
 grub-core/loader/i386/multiboot_mbi.c |   13 +++-
 grub-core/loader/multiboot.c  |   11 ++-
 grub-core/loader/multiboot_elfxx.c|  127 -
 grub-core/loader/multiboot_mbi2.c |  114 +++--
 include/grub/multiboot.h  |   22 +-
 include/multiboot2.h  |   24 +++
 6 files changed, 231 insertions(+), 80 deletions(-)

diff --git a/grub-core/loader/i386/multiboot_mbi.c 
b/grub-core/loader/i386/multiboot_mbi.c
index f60b702..fd7b41b 100644
--- a/grub-core/loader/i386/multiboot_mbi.c
+++ b/grub-core/loader/i386/multiboot_mbi.c
@@ -70,9 +70,18 @@ load_kernel (grub_file_t file, const char *filename,
 char *buffer, struct multiboot_header *header)
 {
   grub_err_t err;
+  mbi_load_data_t mld;
+
+  mld.file = file;
+  mld.filename = filename;
+  mld.buffer = buffer;
+  mld.mbi_ver = 1;
+  mld.relocatable = 0;
+  mld.avoid_efi_boot_services = 0;
+
   if (grub_multiboot_quirks & GRUB_MULTIBOOT_QUIRK_BAD_KLUDGE)
 {
-  err = grub_multiboot_load_elf (file, filename, buffer);
+  err = grub_multiboot_load_elf (&mld);
   if (err == GRUB_ERR_NONE) {
return GRUB_ERR_NONE;
   }
@@ -121,7 +130,7 @@ load_kernel (grub_file_t file, const char *filename,
   return GRUB_ERR_NONE;
 }
 
-  return grub_multiboot_load_elf (file, filename, buffer);
+  return grub_multiboot_load_elf (&mld);
 }
 
 static struct multiboot_header *
diff --git a/grub-core/loader/multiboot.c b/grub-core/loader/multiboot.c
index 18038fd..bd9d5b3 100644
--- a/grub-core/loade