From mboxrd@z Thu Jan 1 00:00:00 1970 From: "Vladimir 'phcoder' Serbinenko" Subject: Re: [GRUB2 PATCH v3 4/4] multiboot2: Add support for relocatable images Date: Thu, 10 Mar 2016 21:41:26 +0100 Message-ID: References: <1456937500-7855-1-git-send-email-daniel.kiper@oracle.com> <1456937500-7855-5-git-send-email-daniel.kiper@oracle.com> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="===============8348962435204489480==" Return-path: Received: from mail6.bemta3.messagelabs.com ([195.245.230.39]) by lists.xen.org with esmtp (Exim 4.84) (envelope-from ) id 1ae7Ok-0000tx-Ds for xen-devel@lists.xenproject.org; Thu, 10 Mar 2016 20:41:30 +0000 Received: by mail-wm0-f67.google.com with SMTP id n205so403137wmf.2 for ; Thu, 10 Mar 2016 12:41:27 -0800 (PST) In-Reply-To: <1456937500-7855-5-git-send-email-daniel.kiper@oracle.com> List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xen.org Sender: "Xen-devel" To: Daniel Kiper Cc: "jgross@suse.com" , "grub-devel@gnu.org" , "eric.snowberg@oracle.com" , "arvidjaar@gmail.com" , "andrew.cooper3@citrix.com" , "cardoe@cardoe.com" , "pgnet.dev@gmail.com" , "roy.franz@linaro.org" , "ning.sun@intel.com" , "david.vrabel@citrix.com" , "jbeulich@suse.com" , "stefano.stabellini@eu.citrix.com" , "xen-devel@lists.xenproject.org" , "qiaowei.ren@intel.com" , "richard.l.maliszewski@intel.com" , "gang.wei@intel.com" , "fu.wei@linaro.org" , "seth.goldberg@oracle.com" List-Id: xen-devel@lists.xenproject.org --===============8348962435204489480== Content-Type: multipart/alternative; boundary=001a1147cd9ca4f527052db7d6d5 --001a1147cd9ca4f527052db7d6d5 Content-Type: text/plain; charset=UTF-8 On Wednesday, March 2, 2016, 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 simply 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. 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_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. > > As I saw multiboot2 protocol is able to consume ET_EXEC and ET_DYN ELF > files. > Potentially we can use ET_DYN file type. It can be build with gcc/ld -pie > option. > However, it contains a lot of unneeded stuff (e.g. INTERP, DYNAMIC, > GNU_EH_FRAME > program headers) and it could be quite difficult to drop them (Hmmm... Is > it > possible to build it properly with custom ld script?). How big are they? Are they a real problem? > So, I have checked ET_EXEC > file type. Sadly in this case linker by default resolves all local symbol > relocations > and removes relocation related sections. Fortunately it is possible to > leave them > as is with simple -q/--emit-relocs ld option. However, output file is > quite fragile > and any operation on it should be done with great care (e.g. strip should > be called > with --strip-unneeded option). So, this solution is not perfect too. It > means that > maybe we should look for better solution. However, I think that we should > not use > any custom tools and focus on functionalities provided by compiler and > binutils. > In this context ld scripts looks quite promising but maybe you have better > solutions. > So, what do you think about that? > Another possibility is to use intermediary .o files like we do for modules and like Linux does for modules AFAIR. > > 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 > > --- > 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 | 6 ++- > grub-core/loader/multiboot.c | 12 ++++-- > grub-core/loader/multiboot_elfxx.c | 28 ++++++++++---- > grub-core/loader/multiboot_mbi2.c | 65 > ++++++++++++++++++++++++++++++--- > include/grub/multiboot.h | 4 +- > include/multiboot2.h | 24 ++++++++++++ > 6 files changed, 120 insertions(+), 19 deletions(-) > > diff --git a/grub-core/loader/i386/multiboot_mbi.c > b/grub-core/loader/i386/multiboot_mbi.c > index f60b702..4fc83ed 100644 > --- a/grub-core/loader/i386/multiboot_mbi.c > +++ b/grub-core/loader/i386/multiboot_mbi.c > @@ -72,7 +72,8 @@ load_kernel (grub_file_t file, const char *filename, > grub_err_t err; > if (grub_multiboot_quirks & GRUB_MULTIBOOT_QUIRK_BAD_KLUDGE) > { > - err = grub_multiboot_load_elf (file, filename, buffer); > + err = grub_multiboot_load_elf (file, filename, buffer, 0, 0, 0, 0, > + GRUB_RELOCATOR_PREFERENCE_NONE, NULL, > 0); > if (err == GRUB_ERR_NONE) { > return GRUB_ERR_NONE; > } > @@ -121,7 +122,8 @@ 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 (file, filename, buffer, 0, 0, 0, 0, > + GRUB_RELOCATOR_PREFERENCE_NONE, NULL, 0); > } > > static struct multiboot_header * > diff --git a/grub-core/loader/multiboot.c b/grub-core/loader/multiboot.c > index 18038fd..c0f51b6 100644 > --- a/grub-core/loader/multiboot.c > +++ b/grub-core/loader/multiboot.c > @@ -208,12 +208,18 @@ static grub_uint64_t highest_load; > /* Load ELF32 or ELF64. */ > grub_err_t > grub_multiboot_load_elf (grub_file_t file, const char *filename, > - void *buffer) > + void *buffer, int relocatable, grub_uint32_t > min_addr, > + grub_uint32_t max_addr, grub_size_t align, > grub_uint32_t preference, > + grub_uint32_t *base_addr, int > avoid_efi_boot_services) > { > if (grub_multiboot_is_elf32 (buffer)) > - return grub_multiboot_load_elf32 (file, filename, buffer); > + return grub_multiboot_load_elf32 (file, filename, buffer, relocatable, > + min_addr, max_addr, align, > preference, > + base_addr, avoid_efi_boot_services); > else if (grub_multiboot_is_elf64 (buffer)) > - return grub_multiboot_load_elf64 (file, filename, buffer); > + return grub_multiboot_load_elf64 (file, filename, buffer, relocatable, > + min_addr, max_addr, align, > preference, > + base_addr, avoid_efi_boot_services); > > return grub_error (GRUB_ERR_UNKNOWN_OS, N_("invalid arch-dependent ELF > magic")); > } > diff --git a/grub-core/loader/multiboot_elfxx.c > b/grub-core/loader/multiboot_elfxx.c > index e3a39b6..0c01569 100644 > --- a/grub-core/loader/multiboot_elfxx.c > +++ b/grub-core/loader/multiboot_elfxx.c > @@ -51,7 +51,10 @@ CONCAT(grub_multiboot_is_elf, XX) (void *buffer) > } > > 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) (grub_file_t file, const char > *filename, > + void *buffer, int relocatable, > grub_uint32_t min_addr, > + grub_uint32_t max_addr, grub_size_t > align, grub_uint32_t preference, > + grub_uint32_t *base_addr, int > avoid_efi_boot_services) > { > Elf_Ehdr *ehdr = (Elf_Ehdr *) buffer; > char *phdr_base; > @@ -89,19 +92,30 @@ CONCAT(grub_multiboot_load_elf, XX) (grub_file_t file, > const char *filename, voi > if (phdr(i)->p_paddr + phdr(i)->p_memsz > highest_load) > highest_load = phdr(i)->p_paddr + phdr(i)->p_memsz; > > - grub_dprintf ("multiboot_loader", "segment %d: paddr=0x%lx, > memsz=0x%lx, vaddr=0x%lx\n", > - i, (long) phdr(i)->p_paddr, (long) > phdr(i)->p_memsz, (long) phdr(i)->p_vaddr); > + grub_dprintf ("multiboot_loader", "segment %d: paddr=0x%lx, > memsz=0x%lx, vaddr=0x%lx," > + "align=0x%lx, relocatable=%d, > avoid_efi_boot_services=%d\n", i, > + (long) phdr(i)->p_paddr, (long) phdr(i)->p_memsz, > (long) phdr(i)->p_vaddr, > + (long) align, relocatable, > avoid_efi_boot_services); > > { > grub_relocator_chunk_t ch; > - err = grub_relocator_alloc_chunk_addr > (grub_multiboot_relocator, > - &ch, phdr(i)->p_paddr, > - phdr(i)->p_memsz); > + > + if (relocatable) > + err = grub_relocator_alloc_chunk_align > (grub_multiboot_relocator, &ch, > + min_addr, max_addr - > phdr(i)->p_memsz, > + phdr(i)->p_memsz, > align ? align : 1, > + preference, > avoid_efi_boot_services); > + else > + err = grub_relocator_alloc_chunk_addr > (grub_multiboot_relocator, > + &ch, phdr(i)->p_paddr, > + phdr(i)->p_memsz); > if (err) > { > grub_dprintf ("multiboot_loader", "Error loading phdr > %d\n", i); > return err; > } > + if (base_addr) > + *base_addr = get_physical_target_address (ch); > source = get_virtual_current_address (ch); > } > > @@ -208,7 +222,7 @@ CONCAT(grub_multiboot_load_elf, XX) (grub_file_t file, > const char *filename, voi > + 1, sh->sh_size, > sh->sh_addralign, > > GRUB_RELOCATOR_PREFERENCE_NONE, > - 0); > + > avoid_efi_boot_services); > if (err) > { > grub_dprintf ("multiboot_loader", "Error loading shdr > %d\n", i); > diff --git a/grub-core/loader/multiboot_mbi2.c > b/grub-core/loader/multiboot_mbi2.c > index ce68f48..03725a1 100644 > --- a/grub-core/loader/multiboot_mbi2.c > +++ b/grub-core/loader/multiboot_mbi2.c > @@ -68,6 +68,7 @@ static grub_size_t elf_sec_num, elf_sec_entsize; > static unsigned elf_sec_shstrndx; > static void *elf_sections; > static int keep_bs = 0; > +static grub_uint32_t base_addr = 0; > > void > grub_multiboot_add_elfsyms (grub_size_t num, grub_size_t entsize, > @@ -107,11 +108,14 @@ grub_multiboot_load (grub_file_t file, const char > *filename) > grub_err_t err; > struct multiboot_header_tag *tag; > struct multiboot_header_tag_address *addr_tag = NULL; > - int entry_specified = 0, efi_entry_specified = 0; > + struct multiboot_header_tag_relocatable *rel_tag; > + int entry_specified = 0, efi_entry_specified = 0, relocatable = 0; > grub_addr_t entry = 0, efi_entry = 0; > - grub_uint32_t console_required = 0; > + grub_uint32_t console_required = 0, min_addr = 0; > + grub_uint32_t max_addr = 0, preference = GRUB_RELOCATOR_PREFERENCE_NONE; > struct multiboot_header_tag_framebuffer *fbtag = NULL; > int accepted_consoles = GRUB_MULTIBOOT_CONSOLE_EGA_TEXT; > + grub_size_t align = 0; > > buffer = grub_malloc (MULTIBOOT_SEARCH); > if (!buffer) > @@ -174,6 +178,7 @@ grub_multiboot_load (grub_file_t file, const char > *filename) > case MULTIBOOT_TAG_TYPE_EFI_BS: > case MULTIBOOT_TAG_TYPE_EFI32_IH: > case MULTIBOOT_TAG_TYPE_EFI64_IH: > + case MULTIBOOT_TAG_TYPE_BASE_ADDR: > break; > > default: > @@ -215,6 +220,27 @@ grub_multiboot_load (grub_file_t file, const char > *filename) > accepted_consoles |= GRUB_MULTIBOOT_CONSOLE_FRAMEBUFFER; > break; > > + case MULTIBOOT_HEADER_TAG_RELOCATABLE: > + relocatable = 1; > + rel_tag = (struct multiboot_header_tag_relocatable *) tag; > + min_addr = rel_tag->min_addr; > + max_addr = rel_tag->max_addr; > + align = rel_tag->align; > + switch (rel_tag->preference) > + { > + case MULTIBOOT_LOAD_PREFERENCE_LOW: > + preference = GRUB_RELOCATOR_PREFERENCE_LOW; > + break; > + > + case MULTIBOOT_LOAD_PREFERENCE_HIGH: > + preference = GRUB_RELOCATOR_PREFERENCE_HIGH; > + break; > + > + default: > + preference = GRUB_RELOCATOR_PREFERENCE_NONE; > + } > + break; > + > /* GRUB always page-aligns modules. */ > case MULTIBOOT_HEADER_TAG_MODULE_ALIGN: > break; > @@ -260,15 +286,22 @@ grub_multiboot_load (grub_file_t file, const char > *filename) > else > code_size = load_size; > > - err = grub_relocator_alloc_chunk_addr (grub_multiboot_relocator, > - &ch, load_addr, > - code_size); > + if (relocatable) > + err = grub_relocator_alloc_chunk_align (grub_multiboot_relocator, > &ch, > + min_addr, max_addr - > code_size, > + code_size, align ? align : > 1, > + preference, keep_bs); > + else > + err = grub_relocator_alloc_chunk_addr (grub_multiboot_relocator, > + &ch, load_addr, > + code_size); > if (err) > { > grub_dprintf ("multiboot_loader", "Error loading aout kludge\n"); > grub_free (buffer); > return err; > } > + base_addr = get_physical_target_address (ch); > source = get_virtual_current_address (ch); > > if ((grub_file_seek (file, offset)) == (grub_off_t) -1) > @@ -290,7 +323,9 @@ grub_multiboot_load (grub_file_t file, const char > *filename) > } > else > { > - err = grub_multiboot_load_elf (file, filename, buffer); > + err = grub_multiboot_load_elf (file, filename, buffer, > + relocatable, min_addr, max_addr, > + align, preference, &base_addr, > keep_bs); > if (err) > { > grub_free (buffer); > @@ -303,6 +338,14 @@ grub_multiboot_load (grub_file_t file, const char > *filename) > else if (entry_specified) > grub_multiboot_payload_eip = entry; > > + if (relocatable) > + { > + if (base_addr > min_addr) > + grub_multiboot_payload_eip += base_addr - min_addr; > + else > + grub_multiboot_payload_eip -= min_addr - base_addr; > + } > + > Why is it relative to min_addr? Sounds like it should be just an offset from base addr. What do ET_DYN files use? > if (fbtag) > err = grub_multiboot_set_console (GRUB_MULTIBOOT_CONSOLE_FRAMEBUFFER, > accepted_consoles, > @@ -409,6 +452,7 @@ grub_multiboot_get_mbi_size (void) > + grub_get_multiboot_mmap_count () > * sizeof (struct multiboot_mmap_entry)), > MULTIBOOT_TAG_ALIGN) > + ALIGN_UP (sizeof (struct multiboot_tag_framebuffer), > MULTIBOOT_TAG_ALIGN) > + + ALIGN_UP (sizeof (struct multiboot_tag_base_addr), > MULTIBOOT_TAG_ALIGN) > #ifdef GRUB_MACHINE_EFI > #ifdef __i386__ > + ALIGN_UP (sizeof (struct multiboot_tag_efi32), MULTIBOOT_TAG_ALIGN) > @@ -698,6 +742,15 @@ grub_multiboot_make_mbi (grub_uint32_t *target) > ptrorig += (2 * sizeof (grub_uint32_t)) / sizeof > (grub_properly_aligned_t); > > { > + struct multiboot_tag_base_addr *tag = (struct multiboot_tag_base_addr > *) ptrorig; > + tag->type = MULTIBOOT_TAG_TYPE_BASE_ADDR; > + tag->size = sizeof (struct multiboot_tag_base_addr); > + tag->base_addr = base_addr; > + ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN) > + / sizeof (grub_properly_aligned_t); > + } > + > + { > struct multiboot_tag_string *tag = (struct multiboot_tag_string *) > ptrorig; > tag->type = MULTIBOOT_TAG_TYPE_CMDLINE; > tag->size = sizeof (struct multiboot_tag_string) + cmdline_size; > diff --git a/include/grub/multiboot.h b/include/grub/multiboot.h > index e13c084..ec322b0 100644 > --- a/include/grub/multiboot.h > +++ b/include/grub/multiboot.h > @@ -94,7 +94,9 @@ grub_multiboot_load (grub_file_t file, const char > *filename); > /* Load ELF32 or ELF64. */ > grub_err_t > grub_multiboot_load_elf (grub_file_t file, const char *filename, > - void *buffer); > + void *buffer, int relocatable, grub_uint32_t > min_addr, > + grub_uint32_t max_addr, grub_size_t align, > grub_uint32_t preference, > + grub_uint32_t *base_addr, int > avoid_efi_boot_services); > extern grub_size_t grub_multiboot_pure_size; > extern grub_size_t grub_multiboot_alloc_mbi; > extern grub_uint32_t grub_multiboot_payload_eip; > diff --git a/include/multiboot2.h b/include/multiboot2.h > index 36a174f..c09bdbc 100644 > --- a/include/multiboot2.h > +++ b/include/multiboot2.h > @@ -62,6 +62,7 @@ > #define MULTIBOOT_TAG_TYPE_EFI_BS 18 > #define MULTIBOOT_TAG_TYPE_EFI32_IH 19 > #define MULTIBOOT_TAG_TYPE_EFI64_IH 20 > +#define MULTIBOOT_TAG_TYPE_BASE_ADDR 21 > > #define MULTIBOOT_HEADER_TAG_END 0 > #define MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST 1 > @@ -72,11 +73,16 @@ > #define MULTIBOOT_HEADER_TAG_MODULE_ALIGN 6 > #define MULTIBOOT_HEADER_TAG_EFI_BS 7 > #define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI64 9 > +#define MULTIBOOT_HEADER_TAG_RELOCATABLE 10 > > #define MULTIBOOT_ARCHITECTURE_I386 0 > #define MULTIBOOT_ARCHITECTURE_MIPS32 4 > #define MULTIBOOT_HEADER_TAG_OPTIONAL 1 > > +#define MULTIBOOT_LOAD_PREFERENCE_NONE 0 > +#define MULTIBOOT_LOAD_PREFERENCE_LOW 1 > +#define MULTIBOOT_LOAD_PREFERENCE_HIGH 2 > + > #define MULTIBOOT_CONSOLE_FLAGS_CONSOLE_REQUIRED 1 > #define MULTIBOOT_CONSOLE_FLAGS_EGA_TEXT_SUPPORTED 2 > > @@ -161,6 +167,17 @@ struct multiboot_header_tag_module_align > multiboot_uint32_t size; > }; > > +struct multiboot_header_tag_relocatable > +{ > + multiboot_uint16_t type; > + multiboot_uint16_t flags; > + multiboot_uint32_t size; > + multiboot_uint32_t min_addr; > + multiboot_uint32_t max_addr; > + multiboot_uint32_t align; > + multiboot_uint32_t preference; > +}; > + > struct multiboot_color > { > multiboot_uint8_t red; > @@ -387,6 +404,13 @@ struct multiboot_tag_efi64_ih > multiboot_uint64_t pointer; > }; > > +struct multiboot_tag_base_addr > +{ > + multiboot_uint32_t type; > + multiboot_uint32_t size; > + multiboot_uint32_t base_addr; > +}; > + > #endif /* ! ASM_FILE */ > > #endif /* ! MULTIBOOT_HEADER */ > -- > 1.7.10.4 > > -- Regards Vladimir 'phcoder' Serbinenko --001a1147cd9ca4f527052db7d6d5 Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable

On Wednesday, March 2, 2016, Daniel Kiper <daniel.kiper@oracle.com> wrote:
Currently multiboot2 protocol loads image exactly at ad= dress 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<= br> 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 simply 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<= br> specified in ELF and multiboot2 headers.

This patch provides all needed machinery to do self relocation in image cod= e.
First of all GRUB2 reads min_addr (min. load addr), max_addr (max. load add= r),
align (required image alignment), preference (it says which memory regions = are
preferred by image, e.g. none, low, high) from multiboot_header_tag_relocat= able
header tag contained in binary. 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_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<= br> ELF relocation data. However, I was asked by Konrad Rzeszutek Wilk and Vlad= imir
'phcoder' Serbinenko to investigate that thing. It looks that relev= ant machinery
could be added to existing code (including this patch) without huge effort.=
Additionally, ELF relocation could live in parallel with self relocation pr= ovided
by this patch. However, during research I realized that first of all we sho= uld
establish the details how ELF relocatable image should look like and how it= should
be build. At least to build proper test/example files.

As I saw multiboot2 protocol is able to consume ET_EXEC and ET_DYN ELF file= s.
Potentially we can use ET_DYN file type. It can be build with gcc/ld -pie o= ption.
However, it contains a lot of unneeded stuff (e.g. INTERP, DYNAMIC, GNU_EH_= FRAME
program headers) and it could be quite difficult to drop them (Hmmm... Is i= t
possible to build it properly with custom ld script?).
How= big are they? Are they a real problem?=C2=A0
So, I have checked ET_EXEC
file type. Sadly in this case linker by default resolves all local symbol r= elocations
and removes relocation related sections. Fortunately it is possible to leav= e them
as is with simple -q/--emit-relocs ld option. However, output file is quite= fragile
and any operation on it should be done with great care (e.g. strip should b= e called
with --strip-unneeded option). So, this solution is not perfect too. It mea= ns that
maybe we should look for better solution. However, I think that we should n= ot use
any custom tools and focus on functionalities provided by compiler and binu= tils.
In this context ld scripts looks quite promising but maybe you have better = solutions.
So, what do you think about that?
=C2=A0Another possib= ility is to use intermediary .o files like we do for modules and like Linux= does for modules AFAIR.

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 abo= ut 3-4 weeks.

Signed-off-by: Daniel Kiper <daniel.kiper@oracle.= com>
---
v3 - suggestions/fixes:
=C2=A0 =C2=A0- reduce number of casts
=C2=A0 =C2=A0 =C2=A0(suggested by Konrad Rzeszutek Wilk),
=C2=A0 =C2=A0- remove unneeded space at the end of line
=C2=A0 =C2=A0 =C2=A0(suggested by Konrad Rzeszutek Wilk),
=C2=A0 =C2=A0- improve commit message
=C2=A0 =C2=A0 =C2=A0(suggested by Konrad Rzeszutek Wilk).
---
=C2=A0grub-core/loader/i386/multiboot_mbi.c |=C2=A0 =C2=A0 6 ++-
=C2=A0grub-core/loader/multiboot.c=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 |=C2= =A0 =C2=A012 ++++--
=C2=A0grub-core/loader/multiboot_elfxx.c=C2=A0 =C2=A0 |=C2=A0 =C2=A028 ++++= ++++++----
=C2=A0grub-core/loader/multiboot_mbi2.c=C2=A0 =C2=A0 =C2=A0|=C2=A0 =C2=A065= ++++++++++++++++++++++++++++++---
=C2=A0include/grub/multiboot.h=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 |=C2=A0 =C2=A0 4 +-
=C2=A0include/multiboot2.h=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 |=C2=A0 =C2=A024 ++++++++++++
=C2=A06 files changed, 120 insertions(+), 19 deletions(-)

diff --git a/grub-core/loader/i386/multiboot_mbi.c b/grub-core/loader/i386/= multiboot_mbi.c
index f60b702..4fc83ed 100644
--- a/grub-core/loader/i386/multiboot_mbi.c
+++ b/grub-core/loader/i386/multiboot_mbi.c
@@ -72,7 +72,8 @@ load_kernel (grub_file_t file, const char *filename,
=C2=A0 =C2=A0grub_err_t err;
=C2=A0 =C2=A0if (grub_multiboot_quirks & GRUB_MULTIBOOT_QUIRK_BAD_KLUDG= E)
=C2=A0 =C2=A0 =C2=A0{
-=C2=A0 =C2=A0 =C2=A0 err =3D grub_multiboot_load_elf (file, filename, buff= er);
+=C2=A0 =C2=A0 =C2=A0 err =3D grub_multiboot_load_elf (file, filename, buff= er, 0, 0, 0, 0,
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 GRUB_RELOCATOR_PREFERE= NCE_NONE, NULL, 0);
=C2=A0 =C2=A0 =C2=A0 =C2=A0if (err =3D=3D GRUB_ERR_NONE) {
=C2=A0 =C2=A0 =C2=A0 =C2=A0 return GRUB_ERR_NONE;
=C2=A0 =C2=A0 =C2=A0 =C2=A0}
@@ -121,7 +122,8 @@ load_kernel (grub_file_t file, const char *filename, =C2=A0 =C2=A0 =C2=A0 =C2=A0return GRUB_ERR_NONE;
=C2=A0 =C2=A0 =C2=A0}

-=C2=A0 return grub_multiboot_load_elf (file, filename, buffer);
+=C2=A0 return grub_multiboot_load_elf (file, filename, buffer, 0, 0, 0, 0,=
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0GRUB_RELOCATOR_PREFERENCE_NONE= , NULL, 0);
=C2=A0}

=C2=A0static struct multiboot_header *
diff --git a/grub-core/loader/multiboot.c b/grub-core/loader/multiboot.c index 18038fd..c0f51b6 100644
--- a/grub-core/loader/multiboot.c
+++ b/grub-core/loader/multiboot.c
@@ -208,12 +208,18 @@ static grub_uint64_t highest_load;
=C2=A0/* Load ELF32 or ELF64.=C2=A0 */
=C2=A0grub_err_t
=C2=A0grub_multiboot_load_elf (grub_file_t file, const char *filename,
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 void *buffer)
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 void *buffer, int relocatable, grub_uint32_t min_addr,
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 grub_uint32_t max_addr, grub_size_t align, grub_uint32_t prefere= nce,
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 grub_uint32_t *base_addr, int avoid_efi_boot_services)
=C2=A0{
=C2=A0 =C2=A0if (grub_multiboot_is_elf32 (buffer))
-=C2=A0 =C2=A0 return grub_multiboot_load_elf32 (file, filename, buffer); +=C2=A0 =C2=A0 return grub_multiboot_load_elf32 (file, filename, buffer, re= locatable,
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0min_addr, max_ad= dr, align, preference,
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0base_addr, avoid= _efi_boot_services);
=C2=A0 =C2=A0else if (grub_multiboot_is_elf64 (buffer))
-=C2=A0 =C2=A0 return grub_multiboot_load_elf64 (file, filename, buffer); +=C2=A0 =C2=A0 return grub_multiboot_load_elf64 (file, filename, buffer, re= locatable,
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0min_addr, max_ad= dr, align, preference,
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0base_addr, avoid= _efi_boot_services);

=C2=A0 =C2=A0return grub_error (GRUB_ERR_UNKNOWN_OS, N_("invalid arch-= dependent ELF magic"));
=C2=A0}
diff --git a/grub-core/loader/multiboot_elfxx.c b/grub-core/loader/multiboo= t_elfxx.c
index e3a39b6..0c01569 100644
--- a/grub-core/loader/multiboot_elfxx.c
+++ b/grub-core/loader/multiboot_elfxx.c
@@ -51,7 +51,10 @@ CONCAT(grub_multiboot_is_elf, XX) (void *buffer)
=C2=A0}

=C2=A0static grub_err_t
-CONCAT(grub_multiboot_load_elf, XX) (grub_file_t file, const char *filenam= e, void *buffer)
+CONCAT(grub_multiboot_load_elf, XX) (grub_file_t file, const char *filenam= e,
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 void *buffer, int relo= catable, grub_uint32_t min_addr,
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 grub_uint32_t max_addr= , grub_size_t align, grub_uint32_t preference,
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 grub_uint32_t *base_ad= dr, int avoid_efi_boot_services)
=C2=A0{
=C2=A0 =C2=A0Elf_Ehdr *ehdr =3D (Elf_Ehdr *) buffer;
=C2=A0 =C2=A0char *phdr_base;
@@ -89,19 +92,30 @@ CONCAT(grub_multiboot_load_elf, XX) (grub_file_t file, = const char *filename, voi
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 if (phdr(i)->p_paddr + phdr(i)->p_= memsz > highest_load)
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 highest_load =3D phdr(i)->p_pa= ddr + phdr(i)->p_memsz;

-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0grub_dprintf ("multiboot_loader&quo= t;, "segment %d: paddr=3D0x%lx, memsz=3D0x%lx, vaddr=3D0x%lx\n",<= br> -=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0i, (long) phdr(i)->p_paddr, (long) phdr(i)->p_memsz, (long)= phdr(i)->p_vaddr);
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0grub_dprintf ("multiboot_loader&quo= t;, "segment %d: paddr=3D0x%lx, memsz=3D0x%lx, vaddr=3D0x%lx," +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0"align=3D0x%lx, relocatable=3D%d, avoid_efi_boot_services=3D= %d\n", i,
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0(long) phdr(i)->p_paddr, (long) phdr(i)->p_memsz, (long) ph= dr(i)->p_vaddr,
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0(long) align, relocatable, avoid_efi_boot_services);

=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 {
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 grub_relocator_chunk_t ch;
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0err =3D grub_relocator_alloc_chun= k_addr (grub_multiboot_relocator,
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 &ch, phdr(i)->p_paddr,
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 phdr(i)->p_memsz);
+
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0if (relocatable)
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0err =3D grub_relocator_all= oc_chunk_align (grub_multiboot_relocator, &ch,
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0min_addr, max_addr - phdr(i)->p= _memsz,
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0phdr(i)->p_memsz, align ? align= : 1,
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0preference, avoid_efi_boot_service= s);
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0else
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0err =3D grub_relocator_all= oc_chunk_addr (grub_multiboot_relocator,
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &ch, phdr(i)->p_paddr,
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 phdr(i)->p_memsz);
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 if (err)
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 {
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 grub_dprintf ("= ;multiboot_loader", "Error loading phdr %d\n", i);
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 return err;
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 }
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0if (base_addr)
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0*base_addr =3D get_physica= l_target_address (ch);
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 source =3D get_virtual_current_ad= dress (ch);
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 }

@@ -208,7 +222,7 @@ CONCAT(grub_multiboot_load_elf, XX) (grub_file_t file, = const char *filename, voi
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 + 1, sh->sh_size,
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 sh->sh_addralign,
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 GRUB_RELOCATOR_PREFERENCE_NONE,
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A00);
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0avoid_efi_boot_services);
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 if (err)
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 {
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 grub_dprintf ("= ;multiboot_loader", "Error loading shdr %d\n", i);
diff --git a/grub-core/loader/multiboot_mbi2.c b/grub-core/loader/multiboot= _mbi2.c
index ce68f48..03725a1 100644
--- a/grub-core/loader/multiboot_mbi2.c
+++ b/grub-core/loader/multiboot_mbi2.c
@@ -68,6 +68,7 @@ static grub_size_t elf_sec_num, elf_sec_entsize;
=C2=A0static unsigned elf_sec_shstrndx;
=C2=A0static void *elf_sections;
=C2=A0static int keep_bs =3D 0;
+static grub_uint32_t base_addr =3D 0;

=C2=A0void
=C2=A0grub_multiboot_add_elfsyms (grub_size_t num, grub_size_t entsize,
@@ -107,11 +108,14 @@ grub_multiboot_load (grub_file_t file, const char *fi= lename)
=C2=A0 =C2=A0grub_err_t err;
=C2=A0 =C2=A0struct multiboot_header_tag *tag;
=C2=A0 =C2=A0struct multiboot_header_tag_address *addr_tag =3D NULL;
-=C2=A0 int entry_specified =3D 0, efi_entry_specified =3D 0;
+=C2=A0 struct multiboot_header_tag_relocatable *rel_tag;
+=C2=A0 int entry_specified =3D 0, efi_entry_specified =3D 0, relocatable = =3D 0;
=C2=A0 =C2=A0grub_addr_t entry =3D 0, efi_entry =3D 0;
-=C2=A0 grub_uint32_t console_required =3D 0;
+=C2=A0 grub_uint32_t console_required =3D 0, min_addr =3D 0;
+=C2=A0 grub_uint32_t max_addr =3D 0, preference =3D GRUB_RELOCATOR_PREFERE= NCE_NONE;
=C2=A0 =C2=A0struct multiboot_header_tag_framebuffer *fbtag =3D NULL;
=C2=A0 =C2=A0int accepted_consoles =3D GRUB_MULTIBOOT_CONSOLE_EGA_TEXT;
+=C2=A0 grub_size_t align =3D 0;

=C2=A0 =C2=A0buffer =3D grub_malloc (MULTIBOOT_SEARCH);
=C2=A0 =C2=A0if (!buffer)
@@ -174,6 +178,7 @@ grub_multiboot_load (grub_file_t file, const char *file= name)
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 case MULTIBOOT_TAG_TYPE_EF= I_BS:
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 case MULTIBOOT_TAG_TYPE_EF= I32_IH:
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 case MULTIBOOT_TAG_TYPE_EF= I64_IH:
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0case MULTIBOOT_TAG_TYPE_BA= SE_ADDR:
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 break;

=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 default:
@@ -215,6 +220,27 @@ grub_multiboot_load (grub_file_t file, const char *fil= ename)
=C2=A0 =C2=A0 =C2=A0 =C2=A0 accepted_consoles |=3D GRUB_MULTIBOOT_CONSOLE_F= RAMEBUFFER;
=C2=A0 =C2=A0 =C2=A0 =C2=A0 break;

+=C2=A0 =C2=A0 =C2=A0 case MULTIBOOT_HEADER_TAG_RELOCATABLE:
+=C2=A0 =C2=A0 =C2=A0 =C2=A0relocatable =3D 1;
+=C2=A0 =C2=A0 =C2=A0 =C2=A0rel_tag =3D (struct multiboot_header_tag_reloca= table *) tag;
+=C2=A0 =C2=A0 =C2=A0 =C2=A0min_addr =3D rel_tag->min_addr;
+=C2=A0 =C2=A0 =C2=A0 =C2=A0max_addr =3D rel_tag->max_addr;
+=C2=A0 =C2=A0 =C2=A0 =C2=A0align =3D rel_tag->align;
+=C2=A0 =C2=A0 =C2=A0 =C2=A0switch (rel_tag->preference)
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0{
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0case MULTIBOOT_LOAD_PREFERENCE_LOW:
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0preference =3D GRUB_RELOCATOR_PRE= FERENCE_LOW;
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0break;
+
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0case MULTIBOOT_LOAD_PREFERENCE_HIGH:
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0preference =3D GRUB_RELOCATOR_PRE= FERENCE_HIGH;
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0break;
+
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0default:
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0preference =3D GRUB_RELOCATOR_PRE= FERENCE_NONE;
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0}
+=C2=A0 =C2=A0 =C2=A0 =C2=A0break;
+
=C2=A0 =C2=A0 =C2=A0 =C2=A0 /* GRUB always page-aligns modules.=C2=A0 */ =C2=A0 =C2=A0 =C2=A0 =C2=A0case MULTIBOOT_HEADER_TAG_MODULE_ALIGN:
=C2=A0 =C2=A0 =C2=A0 =C2=A0 break;
@@ -260,15 +286,22 @@ grub_multiboot_load (grub_file_t file, const char *fi= lename)
=C2=A0 =C2=A0 =C2=A0 =C2=A0else
=C2=A0 =C2=A0 =C2=A0 =C2=A0 code_size =3D load_size;

-=C2=A0 =C2=A0 =C2=A0 err =3D grub_relocator_alloc_chunk_addr (grub_multibo= ot_relocator,
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 &ch, load_addr,
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 code_size);
+=C2=A0 =C2=A0 =C2=A0 if (relocatable)
+=C2=A0 =C2=A0 =C2=A0 =C2=A0err =3D grub_relocator_alloc_chunk_align (grub_= multiboot_relocator, &ch,
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0min_addr, max_addr - code_size,
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0code_size, align ? align : 1,
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0preference, keep_bs);
+=C2=A0 =C2=A0 =C2=A0 else
+=C2=A0 =C2=A0 =C2=A0 =C2=A0err =3D grub_relocator_alloc_chunk_addr (grub_m= ultiboot_relocator,
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 &ch, load_addr,
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 code_size);
=C2=A0 =C2=A0 =C2=A0 =C2=A0if (err)
=C2=A0 =C2=A0 =C2=A0 =C2=A0 {
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 grub_dprintf ("multiboot_loader&quo= t;, "Error loading aout kludge\n");
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 grub_free (buffer);
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 return err;
=C2=A0 =C2=A0 =C2=A0 =C2=A0 }
+=C2=A0 =C2=A0 =C2=A0 base_addr =3D get_physical_target_address (ch);
=C2=A0 =C2=A0 =C2=A0 =C2=A0source =3D get_virtual_current_address (ch);

=C2=A0 =C2=A0 =C2=A0 =C2=A0if ((grub_file_seek (file, offset)) =3D=3D (grub= _off_t) -1)
@@ -290,7 +323,9 @@ grub_multiboot_load (grub_file_t file, const char *file= name)
=C2=A0 =C2=A0 =C2=A0}
=C2=A0 =C2=A0else
=C2=A0 =C2=A0 =C2=A0{
-=C2=A0 =C2=A0 =C2=A0 err =3D grub_multiboot_load_elf (file, filename, buff= er);
+=C2=A0 =C2=A0 =C2=A0 err =3D grub_multiboot_load_elf (file, filename, buff= er,
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 relocatable, min_addr,= max_addr,
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 align, preference, &am= p;base_addr, keep_bs);
=C2=A0 =C2=A0 =C2=A0 =C2=A0if (err)
=C2=A0 =C2=A0 =C2=A0 =C2=A0 {
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 grub_free (buffer);
@@ -303,6 +338,14 @@ grub_multiboot_load (grub_file_t file, const char *fil= ename)
=C2=A0 =C2=A0else if (entry_specified)
=C2=A0 =C2=A0 =C2=A0grub_multiboot_payload_eip =3D entry;

+=C2=A0 if (relocatable)
+=C2=A0 =C2=A0 {
+=C2=A0 =C2=A0 =C2=A0 if (base_addr > min_addr)
+=C2=A0 =C2=A0 =C2=A0 =C2=A0grub_multiboot_payload_eip +=3D base_addr - min= _addr;
+=C2=A0 =C2=A0 =C2=A0 else
+=C2=A0 =C2=A0 =C2=A0 =C2=A0grub_multiboot_payload_eip -=3D min_addr - base= _addr;
+=C2=A0 =C2=A0 }
+
Why is it relative to min_addr? Sounds like it shoul= d be just an offset from base addr. What do ET_DYN files use?=C2=A0
=C2=A0 =C2=A0if (fbtag)
=C2=A0 =C2=A0 =C2=A0err =3D grub_multiboot_set_console (GRUB_MULTIBOOT_CONS= OLE_FRAMEBUFFER,
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 accepted_consol= es,
@@ -409,6 +452,7 @@ grub_multiboot_get_mbi_size (void)
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0+ grub_get_mu= ltiboot_mmap_count ()
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0* sizeof (str= uct multiboot_mmap_entry)), MULTIBOOT_TAG_ALIGN)
=C2=A0 =C2=A0 =C2=A0+ ALIGN_UP (sizeof (struct multiboot_tag_framebuffer), = MULTIBOOT_TAG_ALIGN)
+=C2=A0 =C2=A0 + ALIGN_UP (sizeof (struct multiboot_tag_base_addr), MULTIBO= OT_TAG_ALIGN)
=C2=A0#ifdef GRUB_MACHINE_EFI
=C2=A0#ifdef __i386__
=C2=A0 =C2=A0 =C2=A0+ ALIGN_UP (sizeof (struct multiboot_tag_efi32), MULTIB= OOT_TAG_ALIGN)
@@ -698,6 +742,15 @@ grub_multiboot_make_mbi (grub_uint32_t *target)
=C2=A0 =C2=A0ptrorig +=3D (2 * sizeof (grub_uint32_t)) / sizeof (grub_prope= rly_aligned_t);

=C2=A0 =C2=A0{
+=C2=A0 =C2=A0 struct multiboot_tag_base_addr *tag =3D (struct multiboot_ta= g_base_addr *) ptrorig;
+=C2=A0 =C2=A0 tag->type =3D MULTIBOOT_TAG_TYPE_BASE_ADDR;
+=C2=A0 =C2=A0 tag->size =3D sizeof (struct multiboot_tag_base_addr); +=C2=A0 =C2=A0 tag->base_addr =3D base_addr;
+=C2=A0 =C2=A0 ptrorig +=3D ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN) +=C2=A0 =C2=A0 =C2=A0 =C2=A0/ sizeof (grub_properly_aligned_t);
+=C2=A0 }
+
+=C2=A0 {
=C2=A0 =C2=A0 =C2=A0struct multiboot_tag_string *tag =3D (struct multiboot_= tag_string *) ptrorig;
=C2=A0 =C2=A0 =C2=A0tag->type =3D MULTIBOOT_TAG_TYPE_CMDLINE;
=C2=A0 =C2=A0 =C2=A0tag->size =3D sizeof (struct multiboot_tag_string) += cmdline_size;
diff --git a/include/grub/multiboot.h b/include/grub/multiboot.h
index e13c084..ec322b0 100644
--- a/include/grub/multiboot.h
+++ b/include/grub/multiboot.h
@@ -94,7 +94,9 @@ grub_multiboot_load (grub_file_t file, const char *filena= me);
=C2=A0/* Load ELF32 or ELF64.=C2=A0 */
=C2=A0grub_err_t
=C2=A0grub_multiboot_load_elf (grub_file_t file, const char *filename,
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 void *buffer);
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 void *buffer, int relocatable, grub_uint32_t min_addr,
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 grub_uint32_t max_addr, grub_size_t align, grub_uint32_t prefere= nce,
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 grub_uint32_t *base_addr, int avoid_efi_boot_services);
=C2=A0extern grub_size_t grub_multiboot_pure_size;
=C2=A0extern grub_size_t grub_multiboot_alloc_mbi;
=C2=A0extern grub_uint32_t grub_multiboot_payload_eip;
diff --git a/include/multiboot2.h b/include/multiboot2.h
index 36a174f..c09bdbc 100644
--- a/include/multiboot2.h
+++ b/include/multiboot2.h
@@ -62,6 +62,7 @@
=C2=A0#define MULTIBOOT_TAG_TYPE_EFI_BS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 18
=C2=A0#define MULTIBOOT_TAG_TYPE_EFI32_IH=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= 19
=C2=A0#define MULTIBOOT_TAG_TYPE_EFI64_IH=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= 20
+#define MULTIBOOT_TAG_TYPE_BASE_ADDR=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A021
=C2=A0#define MULTIBOOT_HEADER_TAG_END=C2=A0 0
=C2=A0#define MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST=C2=A0 1
@@ -72,11 +73,16 @@
=C2=A0#define MULTIBOOT_HEADER_TAG_MODULE_ALIGN=C2=A0 6
=C2=A0#define MULTIBOOT_HEADER_TAG_EFI_BS=C2=A0 7
=C2=A0#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI64=C2=A0 9
+#define MULTIBOOT_HEADER_TAG_RELOCATABLE=C2=A0 10

=C2=A0#define MULTIBOOT_ARCHITECTURE_I386=C2=A0 0
=C2=A0#define MULTIBOOT_ARCHITECTURE_MIPS32=C2=A0 4
=C2=A0#define MULTIBOOT_HEADER_TAG_OPTIONAL 1

+#define MULTIBOOT_LOAD_PREFERENCE_NONE 0
+#define MULTIBOOT_LOAD_PREFERENCE_LOW 1
+#define MULTIBOOT_LOAD_PREFERENCE_HIGH 2
+
=C2=A0#define MULTIBOOT_CONSOLE_FLAGS_CONSOLE_REQUIRED 1
=C2=A0#define MULTIBOOT_CONSOLE_FLAGS_EGA_TEXT_SUPPORTED 2

@@ -161,6 +167,17 @@ struct multiboot_header_tag_module_align
=C2=A0 =C2=A0multiboot_uint32_t size;
=C2=A0};

+struct multiboot_header_tag_relocatable
+{
+=C2=A0 multiboot_uint16_t type;
+=C2=A0 multiboot_uint16_t flags;
+=C2=A0 multiboot_uint32_t size;
+=C2=A0 multiboot_uint32_t min_addr;
+=C2=A0 multiboot_uint32_t max_addr;
+=C2=A0 multiboot_uint32_t align;
+=C2=A0 multiboot_uint32_t preference;
+};
+
=C2=A0struct multiboot_color
=C2=A0{
=C2=A0 =C2=A0multiboot_uint8_t red;
@@ -387,6 +404,13 @@ struct multiboot_tag_efi64_ih
=C2=A0 =C2=A0multiboot_uint64_t pointer;
=C2=A0};

+struct multiboot_tag_base_addr
+{
+=C2=A0 multiboot_uint32_t type;
+=C2=A0 multiboot_uint32_t size;
+=C2=A0 multiboot_uint32_t base_addr;
+};
+
=C2=A0#endif /* ! ASM_FILE */

=C2=A0#endif /* ! MULTIBOOT_HEADER */
--
1.7.10.4



--
Regards
Vladimir 'phcoder' Serbinenk= o

--001a1147cd9ca4f527052db7d6d5-- --===============8348962435204489480== Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: base64 Content-Disposition: inline X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18KWGVuLWRldmVs IG1haWxpbmcgbGlzdApYZW4tZGV2ZWxAbGlzdHMueGVuLm9yZwpodHRwOi8vbGlzdHMueGVuLm9y Zy94ZW4tZGV2ZWwK --===============8348962435204489480==--