Re: [PATCH v2 06/13] x86/efi: Build our own EFI services pointer table

2014-03-26 Thread Matt Fleming
On Tue, 25 Mar, at 03:47:23PM, Roy Franz wrote:
> 
> I have sent a patch (attempted to reply using git-send-email) that
> adds the macro for x86 and updates efi-stub-helper.c.  If you could
> add this to your series for 3.15 that would be great, as then we would
> not have any x86 changes in the ARM EFI stub series.

Normally my response would be "nope" because the time for getting stuff
into tip for the upcoming merge window has come and gone.

However, in this particular case I think we may be OK because it's
simple macro munging, and we can prove by looking at the generated
object code before and after that there's zero changes (which I did).

So it really comes down to what Peter and Ingo are comfortable with.

Peter, Ingo, I've attached the patch. Do you think this is something
that we could get in for the merge window, possibly the end so it gets
some time to bake in linux-next? It would help the ARM folks out for the
next cycle because it's one less dependency they need to track.

- >8 -

>From 0a64e62d455e7ff498d10d359b9cf2d136a7e1d7 Mon Sep 17 00:00:00 2001
From: Matt Fleming 
Date: Sat, 22 Mar 2014 10:09:01 +
Subject: [PATCH] efi: Abstract x86 efi_early calls

The ARM EFI boot stub doesn't need to care about the efi_early
infrastructure that x86 requires in order to do mixed mode thunking. So
wrap everything up in an efi_call_early() macro.

This allows x86 to do the necessary indirection jumps to call whatever
firmware interface is necessary (native or mixed mode), but also allows
the ARM folks to mask the fact that they don't support relocation in the
boot stub and need to pass 'sys_table_arg' to every function.

Signed-off-by: Matt Fleming 
---
 arch/x86/boot/compressed/eboot.c   | 155 -
 drivers/firmware/efi/efi-stub-helper.c |  44 +-
 2 files changed, 98 insertions(+), 101 deletions(-)

diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index 5e1ba4fa3f79..1e6146137f8e 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -21,6 +21,9 @@ static efi_system_table_t *sys_table;
 
 static struct efi_config *efi_early;
 
+#define efi_call_early(f, ...) \
+   efi_early->call(efi_early->f, __VA_ARGS__);
+
 #define BOOT_SERVICES(bits)\
 static void setup_boot_services##bits(struct efi_config *c)\
 {  \
@@ -78,8 +81,8 @@ __file_size32(void *__fh, efi_char16_t *filename_16,
}
 
 grow:
-   status = efi_early->call(efi_early->allocate_pool, EFI_LOADER_DATA,
-info_sz, (void **));
+   status = efi_call_early(allocate_pool, EFI_LOADER_DATA,
+   info_sz, (void **));
if (status != EFI_SUCCESS) {
efi_printk(sys_table, "Failed to alloc mem for file info\n");
return status;
@@ -88,12 +91,12 @@ grow:
status = efi_early->call((unsigned long)h->get_info, h, _guid,
 _sz, info);
if (status == EFI_BUFFER_TOO_SMALL) {
-   efi_early->call(efi_early->free_pool, info);
+   efi_call_early(free_pool, info);
goto grow;
}
 
*file_sz = info->file_size;
-   efi_early->call(efi_early->free_pool, info);
+   efi_call_early(free_pool, info);
 
if (status != EFI_SUCCESS)
efi_printk(sys_table, "Failed to get initrd info\n");
@@ -131,8 +134,8 @@ __file_size64(void *__fh, efi_char16_t *filename_16,
}
 
 grow:
-   status = efi_early->call(efi_early->allocate_pool, EFI_LOADER_DATA,
-info_sz, (void **));
+   status = efi_call_early(allocate_pool, EFI_LOADER_DATA,
+   info_sz, (void **));
if (status != EFI_SUCCESS) {
efi_printk(sys_table, "Failed to alloc mem for file info\n");
return status;
@@ -141,12 +144,12 @@ grow:
status = efi_early->call((unsigned long)h->get_info, h, _guid,
 _sz, info);
if (status == EFI_BUFFER_TOO_SMALL) {
-   efi_early->call(efi_early->free_pool, info);
+   efi_call_early(free_pool, info);
goto grow;
}
 
*file_sz = info->file_size;
-   efi_early->call(efi_early->free_pool, info);
+   efi_call_early(free_pool, info);
 
if (status != EFI_SUCCESS)
efi_printk(sys_table, "Failed to get initrd info\n");
@@ -204,8 +207,8 @@ static inline efi_status_t __open_volume32(void *__image, 
void **__fh)
void *handle = (void *)(unsigned long)image->device_handle;
unsigned long func;
 
-   status = efi_early->call(efi_early->handle_protocol, handle,
-_proto, (void **));
+   status = 

Re: [PATCH v2 06/13] x86/efi: Build our own EFI services pointer table

2014-03-26 Thread Matt Fleming
On Tue, 25 Mar, at 03:47:23PM, Roy Franz wrote:
 
 I have sent a patch (attempted to reply using git-send-email) that
 adds the macro for x86 and updates efi-stub-helper.c.  If you could
 add this to your series for 3.15 that would be great, as then we would
 not have any x86 changes in the ARM EFI stub series.

Normally my response would be nope because the time for getting stuff
into tip for the upcoming merge window has come and gone.

However, in this particular case I think we may be OK because it's
simple macro munging, and we can prove by looking at the generated
object code before and after that there's zero changes (which I did).

So it really comes down to what Peter and Ingo are comfortable with.

Peter, Ingo, I've attached the patch. Do you think this is something
that we could get in for the merge window, possibly the end so it gets
some time to bake in linux-next? It would help the ARM folks out for the
next cycle because it's one less dependency they need to track.

- 8 -

From 0a64e62d455e7ff498d10d359b9cf2d136a7e1d7 Mon Sep 17 00:00:00 2001
From: Matt Fleming matt.flem...@intel.com
Date: Sat, 22 Mar 2014 10:09:01 +
Subject: [PATCH] efi: Abstract x86 efi_early calls

The ARM EFI boot stub doesn't need to care about the efi_early
infrastructure that x86 requires in order to do mixed mode thunking. So
wrap everything up in an efi_call_early() macro.

This allows x86 to do the necessary indirection jumps to call whatever
firmware interface is necessary (native or mixed mode), but also allows
the ARM folks to mask the fact that they don't support relocation in the
boot stub and need to pass 'sys_table_arg' to every function.

Signed-off-by: Matt Fleming matt.flem...@intel.com
---
 arch/x86/boot/compressed/eboot.c   | 155 -
 drivers/firmware/efi/efi-stub-helper.c |  44 +-
 2 files changed, 98 insertions(+), 101 deletions(-)

diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index 5e1ba4fa3f79..1e6146137f8e 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -21,6 +21,9 @@ static efi_system_table_t *sys_table;
 
 static struct efi_config *efi_early;
 
+#define efi_call_early(f, ...) \
+   efi_early-call(efi_early-f, __VA_ARGS__);
+
 #define BOOT_SERVICES(bits)\
 static void setup_boot_services##bits(struct efi_config *c)\
 {  \
@@ -78,8 +81,8 @@ __file_size32(void *__fh, efi_char16_t *filename_16,
}
 
 grow:
-   status = efi_early-call(efi_early-allocate_pool, EFI_LOADER_DATA,
-info_sz, (void **)info);
+   status = efi_call_early(allocate_pool, EFI_LOADER_DATA,
+   info_sz, (void **)info);
if (status != EFI_SUCCESS) {
efi_printk(sys_table, Failed to alloc mem for file info\n);
return status;
@@ -88,12 +91,12 @@ grow:
status = efi_early-call((unsigned long)h-get_info, h, info_guid,
 info_sz, info);
if (status == EFI_BUFFER_TOO_SMALL) {
-   efi_early-call(efi_early-free_pool, info);
+   efi_call_early(free_pool, info);
goto grow;
}
 
*file_sz = info-file_size;
-   efi_early-call(efi_early-free_pool, info);
+   efi_call_early(free_pool, info);
 
if (status != EFI_SUCCESS)
efi_printk(sys_table, Failed to get initrd info\n);
@@ -131,8 +134,8 @@ __file_size64(void *__fh, efi_char16_t *filename_16,
}
 
 grow:
-   status = efi_early-call(efi_early-allocate_pool, EFI_LOADER_DATA,
-info_sz, (void **)info);
+   status = efi_call_early(allocate_pool, EFI_LOADER_DATA,
+   info_sz, (void **)info);
if (status != EFI_SUCCESS) {
efi_printk(sys_table, Failed to alloc mem for file info\n);
return status;
@@ -141,12 +144,12 @@ grow:
status = efi_early-call((unsigned long)h-get_info, h, info_guid,
 info_sz, info);
if (status == EFI_BUFFER_TOO_SMALL) {
-   efi_early-call(efi_early-free_pool, info);
+   efi_call_early(free_pool, info);
goto grow;
}
 
*file_sz = info-file_size;
-   efi_early-call(efi_early-free_pool, info);
+   efi_call_early(free_pool, info);
 
if (status != EFI_SUCCESS)
efi_printk(sys_table, Failed to get initrd info\n);
@@ -204,8 +207,8 @@ static inline efi_status_t __open_volume32(void *__image, 
void **__fh)
void *handle = (void *)(unsigned long)image-device_handle;
unsigned long func;
 
-   status = efi_early-call(efi_early-handle_protocol, handle,
-fs_proto, (void 

Re: [PATCH v2 06/13] x86/efi: Build our own EFI services pointer table

2014-03-25 Thread Roy Franz
On Sat, Mar 22, 2014 at 1:16 PM, Roy Franz  wrote:
> On Sat, Mar 22, 2014 at 4:05 AM, Matt Fleming  wrote:
>> On Fri, 21 Mar, at 05:52:29PM, Roy Franz wrote:
>>>
>>> For both arm32 and arm64 the Linux and EFI calling conventions are the
>>> same, so we are directly invoking the function pointers in the
>>> boot_services table.  This gives us type checking of those calls,
>>> which is nice.The efi_call_physN macros for ARM are currently simply:
>>> #define efi_call_phys2(f, a1, a2)f(a1, a2)
>>>
>>> With the changes in this patch, we can't do this anymore, as we were
>>> relying on some macro processing to handle this differently on ARM.
>>
>> But on the plus side, you no longer have to implement all those
>> efi_call_physX() macros ;-)
>>
>>> I'd like to propose something like for following (my variadic macros
>>> may not be quite right)
>>>
>>> for x86:
>>> #define efi_call_early(...) efi_early->call(__VA_ARGS__)
>>>
>>> for arm it would be:
>>> #define efi_call_early(function, ...) efi_early->function(__VA_ARGS__)
>>
>> Close enough.
>>
>>> This would allow us to define the efi_config struct with typed
>>> function pointers for ARM, and retain the direct invocation along with
>>> type checking.  This returns to using a macro, but I think we should
>>> be able to use a variadic macro instead of the 6 separate macros we
>>> had before.
>>>
>>> I plan to use the above technique to incorporate these changes into
>>> arm64/arm32, barring any better ideas or objections.
>>
>> Actually, this should be enough to fix this up on ARM,
>>
>> #define efi_call_early(f, ...)  \
>> sys_table_arg->boottime->f(__VA_ARGS__);
>>
>> Then you don't need any of the efi_config stuff.
>
> Even better.  I had overlooked that the efi_config variables had identical 
> names
> as the boot services.

I have sent a patch (attempted to reply using git-send-email) that
adds the macro
for x86 and updates efi-stub-helper.c.  If you could add this to your series for
3.15 that would be great, as then we would not have any x86 changes in
the ARM EFI stub series.

Thanks,
Roy


>>
>> Yes, the fact that we're making use of the sys_table_arg is invisible at
>> the call-site, but meh. Not sure that's a big deal. It allows us to use
>> efi_call_early() in the x86 code without needlessly passing 'sys_table'
>> around, since we've got a global pointer to it anyhow.
>>
>> -- >8 --
>>
>> From 5fcc1036d143802e321a745b2c3d793ddb8369ac Mon Sep 17 00:00:00 2001
>> From: Matt Fleming 
>> Date: Sat, 22 Mar 2014 10:09:01 +
>> Subject: [PATCH] efi: Abstract x86 efi_early calls
>>
>> The ARM EFI boot stub doesn't need to care about the efi_early
>> infrastructure that x86 requires in order to do mixed mode thunking. So
>> wrap everything up in an efi_call_early() macro, which saves ARM having
>> to implement efi_config.
>>
>> This allows x86 to do the necessary indirect jumps to call whatever
>> firmware interface is available (native or mixed mode), and at the same
>> time allows ARM to use the C type system for parameter checking by
>> implementing efi_early_call() like so,
>>
>> #define efi_call_early(f, ...)  \
>> system_table_arg->boottime->f(__VA_ARGS__);
>>
>> Signed-off-by: Matt Fleming 
>> ---
>>  arch/x86/boot/compressed/eboot.c   | 155 
>> -
>>  drivers/firmware/efi/efi-stub-helper.c |  44 +-
>>  2 files changed, 98 insertions(+), 101 deletions(-)
>>
>> diff --git a/arch/x86/boot/compressed/eboot.c 
>> b/arch/x86/boot/compressed/eboot.c
>> index 5e1ba4fa3f79..1e6146137f8e 100644
>> --- a/arch/x86/boot/compressed/eboot.c
>> +++ b/arch/x86/boot/compressed/eboot.c
>> @@ -21,6 +21,9 @@ static efi_system_table_t *sys_table;
>>
>>  static struct efi_config *efi_early;
>>
>> +#define efi_call_early(f, ...) \
>> +   efi_early->call(efi_early->f, __VA_ARGS__);
>> +
>>  #define BOOT_SERVICES(bits)\
>>  static void setup_boot_services##bits(struct efi_config *c)\
>>  {  \
>> @@ -78,8 +81,8 @@ __file_size32(void *__fh, efi_char16_t *filename_16,
>> }
>>
>>  grow:
>> -   status = efi_early->call(efi_early->allocate_pool, EFI_LOADER_DATA,
>> -info_sz, (void **));
>> +   status = efi_call_early(allocate_pool, EFI_LOADER_DATA,
>> +   info_sz, (void **));
>> if (status != EFI_SUCCESS) {
>> efi_printk(sys_table, "Failed to alloc mem for file info\n");
>> return status;
>> @@ -88,12 +91,12 @@ grow:
>> status = efi_early->call((unsigned long)h->get_info, h, _guid,
>>  _sz, info);
>> if (status == EFI_BUFFER_TOO_SMALL) {
>> -   efi_early->call(efi_early->free_pool, 

Re: [PATCH v2 06/13] x86/efi: Build our own EFI services pointer table

2014-03-25 Thread Roy Franz
On Sat, Mar 22, 2014 at 1:16 PM, Roy Franz roy.fr...@linaro.org wrote:
 On Sat, Mar 22, 2014 at 4:05 AM, Matt Fleming m...@console-pimps.org wrote:
 On Fri, 21 Mar, at 05:52:29PM, Roy Franz wrote:

 For both arm32 and arm64 the Linux and EFI calling conventions are the
 same, so we are directly invoking the function pointers in the
 boot_services table.  This gives us type checking of those calls,
 which is nice.The efi_call_physN macros for ARM are currently simply:
 #define efi_call_phys2(f, a1, a2)f(a1, a2)

 With the changes in this patch, we can't do this anymore, as we were
 relying on some macro processing to handle this differently on ARM.

 But on the plus side, you no longer have to implement all those
 efi_call_physX() macros ;-)

 I'd like to propose something like for following (my variadic macros
 may not be quite right)

 for x86:
 #define efi_call_early(...) efi_early-call(__VA_ARGS__)

 for arm it would be:
 #define efi_call_early(function, ...) efi_early-function(__VA_ARGS__)

 Close enough.

 This would allow us to define the efi_config struct with typed
 function pointers for ARM, and retain the direct invocation along with
 type checking.  This returns to using a macro, but I think we should
 be able to use a variadic macro instead of the 6 separate macros we
 had before.

 I plan to use the above technique to incorporate these changes into
 arm64/arm32, barring any better ideas or objections.

 Actually, this should be enough to fix this up on ARM,

 #define efi_call_early(f, ...)  \
 sys_table_arg-boottime-f(__VA_ARGS__);

 Then you don't need any of the efi_config stuff.

 Even better.  I had overlooked that the efi_config variables had identical 
 names
 as the boot services.

I have sent a patch (attempted to reply using git-send-email) that
adds the macro
for x86 and updates efi-stub-helper.c.  If you could add this to your series for
3.15 that would be great, as then we would not have any x86 changes in
the ARM EFI stub series.

Thanks,
Roy



 Yes, the fact that we're making use of the sys_table_arg is invisible at
 the call-site, but meh. Not sure that's a big deal. It allows us to use
 efi_call_early() in the x86 code without needlessly passing 'sys_table'
 around, since we've got a global pointer to it anyhow.

 -- 8 --

 From 5fcc1036d143802e321a745b2c3d793ddb8369ac Mon Sep 17 00:00:00 2001
 From: Matt Fleming matt.flem...@intel.com
 Date: Sat, 22 Mar 2014 10:09:01 +
 Subject: [PATCH] efi: Abstract x86 efi_early calls

 The ARM EFI boot stub doesn't need to care about the efi_early
 infrastructure that x86 requires in order to do mixed mode thunking. So
 wrap everything up in an efi_call_early() macro, which saves ARM having
 to implement efi_config.

 This allows x86 to do the necessary indirect jumps to call whatever
 firmware interface is available (native or mixed mode), and at the same
 time allows ARM to use the C type system for parameter checking by
 implementing efi_early_call() like so,

 #define efi_call_early(f, ...)  \
 system_table_arg-boottime-f(__VA_ARGS__);

 Signed-off-by: Matt Fleming matt.flem...@intel.com
 ---
  arch/x86/boot/compressed/eboot.c   | 155 
 -
  drivers/firmware/efi/efi-stub-helper.c |  44 +-
  2 files changed, 98 insertions(+), 101 deletions(-)

 diff --git a/arch/x86/boot/compressed/eboot.c 
 b/arch/x86/boot/compressed/eboot.c
 index 5e1ba4fa3f79..1e6146137f8e 100644
 --- a/arch/x86/boot/compressed/eboot.c
 +++ b/arch/x86/boot/compressed/eboot.c
 @@ -21,6 +21,9 @@ static efi_system_table_t *sys_table;

  static struct efi_config *efi_early;

 +#define efi_call_early(f, ...) \
 +   efi_early-call(efi_early-f, __VA_ARGS__);
 +
  #define BOOT_SERVICES(bits)\
  static void setup_boot_services##bits(struct efi_config *c)\
  {  \
 @@ -78,8 +81,8 @@ __file_size32(void *__fh, efi_char16_t *filename_16,
 }

  grow:
 -   status = efi_early-call(efi_early-allocate_pool, EFI_LOADER_DATA,
 -info_sz, (void **)info);
 +   status = efi_call_early(allocate_pool, EFI_LOADER_DATA,
 +   info_sz, (void **)info);
 if (status != EFI_SUCCESS) {
 efi_printk(sys_table, Failed to alloc mem for file info\n);
 return status;
 @@ -88,12 +91,12 @@ grow:
 status = efi_early-call((unsigned long)h-get_info, h, info_guid,
  info_sz, info);
 if (status == EFI_BUFFER_TOO_SMALL) {
 -   efi_early-call(efi_early-free_pool, info);
 +   efi_call_early(free_pool, info);
 goto grow;
 }

 *file_sz = info-file_size;
 -   

Re: [PATCH v2 06/13] x86/efi: Build our own EFI services pointer table

2014-03-22 Thread Roy Franz
On Sat, Mar 22, 2014 at 4:05 AM, Matt Fleming  wrote:
> On Fri, 21 Mar, at 05:52:29PM, Roy Franz wrote:
>>
>> For both arm32 and arm64 the Linux and EFI calling conventions are the
>> same, so we are directly invoking the function pointers in the
>> boot_services table.  This gives us type checking of those calls,
>> which is nice.The efi_call_physN macros for ARM are currently simply:
>> #define efi_call_phys2(f, a1, a2)f(a1, a2)
>>
>> With the changes in this patch, we can't do this anymore, as we were
>> relying on some macro processing to handle this differently on ARM.
>
> But on the plus side, you no longer have to implement all those
> efi_call_physX() macros ;-)
>
>> I'd like to propose something like for following (my variadic macros
>> may not be quite right)
>>
>> for x86:
>> #define efi_call_early(...) efi_early->call(__VA_ARGS__)
>>
>> for arm it would be:
>> #define efi_call_early(function, ...) efi_early->function(__VA_ARGS__)
>
> Close enough.
>
>> This would allow us to define the efi_config struct with typed
>> function pointers for ARM, and retain the direct invocation along with
>> type checking.  This returns to using a macro, but I think we should
>> be able to use a variadic macro instead of the 6 separate macros we
>> had before.
>>
>> I plan to use the above technique to incorporate these changes into
>> arm64/arm32, barring any better ideas or objections.
>
> Actually, this should be enough to fix this up on ARM,
>
> #define efi_call_early(f, ...)  \
> sys_table_arg->boottime->f(__VA_ARGS__);
>
> Then you don't need any of the efi_config stuff.

Even better.  I had overlooked that the efi_config variables had identical names
as the boot services.
>
> Yes, the fact that we're making use of the sys_table_arg is invisible at
> the call-site, but meh. Not sure that's a big deal. It allows us to use
> efi_call_early() in the x86 code without needlessly passing 'sys_table'
> around, since we've got a global pointer to it anyhow.
>
> -- >8 --
>
> From 5fcc1036d143802e321a745b2c3d793ddb8369ac Mon Sep 17 00:00:00 2001
> From: Matt Fleming 
> Date: Sat, 22 Mar 2014 10:09:01 +
> Subject: [PATCH] efi: Abstract x86 efi_early calls
>
> The ARM EFI boot stub doesn't need to care about the efi_early
> infrastructure that x86 requires in order to do mixed mode thunking. So
> wrap everything up in an efi_call_early() macro, which saves ARM having
> to implement efi_config.
>
> This allows x86 to do the necessary indirect jumps to call whatever
> firmware interface is available (native or mixed mode), and at the same
> time allows ARM to use the C type system for parameter checking by
> implementing efi_early_call() like so,
>
> #define efi_call_early(f, ...)  \
> system_table_arg->boottime->f(__VA_ARGS__);
>
> Signed-off-by: Matt Fleming 
> ---
>  arch/x86/boot/compressed/eboot.c   | 155 
> -
>  drivers/firmware/efi/efi-stub-helper.c |  44 +-
>  2 files changed, 98 insertions(+), 101 deletions(-)
>
> diff --git a/arch/x86/boot/compressed/eboot.c 
> b/arch/x86/boot/compressed/eboot.c
> index 5e1ba4fa3f79..1e6146137f8e 100644
> --- a/arch/x86/boot/compressed/eboot.c
> +++ b/arch/x86/boot/compressed/eboot.c
> @@ -21,6 +21,9 @@ static efi_system_table_t *sys_table;
>
>  static struct efi_config *efi_early;
>
> +#define efi_call_early(f, ...) \
> +   efi_early->call(efi_early->f, __VA_ARGS__);
> +
>  #define BOOT_SERVICES(bits)\
>  static void setup_boot_services##bits(struct efi_config *c)\
>  {  \
> @@ -78,8 +81,8 @@ __file_size32(void *__fh, efi_char16_t *filename_16,
> }
>
>  grow:
> -   status = efi_early->call(efi_early->allocate_pool, EFI_LOADER_DATA,
> -info_sz, (void **));
> +   status = efi_call_early(allocate_pool, EFI_LOADER_DATA,
> +   info_sz, (void **));
> if (status != EFI_SUCCESS) {
> efi_printk(sys_table, "Failed to alloc mem for file info\n");
> return status;
> @@ -88,12 +91,12 @@ grow:
> status = efi_early->call((unsigned long)h->get_info, h, _guid,
>  _sz, info);
> if (status == EFI_BUFFER_TOO_SMALL) {
> -   efi_early->call(efi_early->free_pool, info);
> +   efi_call_early(free_pool, info);
> goto grow;
> }
>
> *file_sz = info->file_size;
> -   efi_early->call(efi_early->free_pool, info);
> +   efi_call_early(free_pool, info);
>
> if (status != EFI_SUCCESS)
> efi_printk(sys_table, "Failed to get initrd info\n");
> @@ -131,8 +134,8 @@ __file_size64(void *__fh, efi_char16_t *filename_16,
> }
>
>  

Re: [PATCH v2 06/13] x86/efi: Build our own EFI services pointer table

2014-03-22 Thread Matt Fleming
On Fri, 21 Mar, at 05:52:29PM, Roy Franz wrote:
> 
> For both arm32 and arm64 the Linux and EFI calling conventions are the
> same, so we are directly invoking the function pointers in the
> boot_services table.  This gives us type checking of those calls,
> which is nice.The efi_call_physN macros for ARM are currently simply:
> #define efi_call_phys2(f, a1, a2)f(a1, a2)
> 
> With the changes in this patch, we can't do this anymore, as we were
> relying on some macro processing to handle this differently on ARM.

But on the plus side, you no longer have to implement all those
efi_call_physX() macros ;-)

> I'd like to propose something like for following (my variadic macros
> may not be quite right)
> 
> for x86:
> #define efi_call_early(...) efi_early->call(__VA_ARGS__)
> 
> for arm it would be:
> #define efi_call_early(function, ...) efi_early->function(__VA_ARGS__)

Close enough.

> This would allow us to define the efi_config struct with typed
> function pointers for ARM, and retain the direct invocation along with
> type checking.  This returns to using a macro, but I think we should
> be able to use a variadic macro instead of the 6 separate macros we
> had before.
> 
> I plan to use the above technique to incorporate these changes into
> arm64/arm32, barring any better ideas or objections.

Actually, this should be enough to fix this up on ARM,

#define efi_call_early(f, ...)  \
sys_table_arg->boottime->f(__VA_ARGS__);

Then you don't need any of the efi_config stuff.

Yes, the fact that we're making use of the sys_table_arg is invisible at
the call-site, but meh. Not sure that's a big deal. It allows us to use
efi_call_early() in the x86 code without needlessly passing 'sys_table'
around, since we've got a global pointer to it anyhow.

-- >8 --

>From 5fcc1036d143802e321a745b2c3d793ddb8369ac Mon Sep 17 00:00:00 2001
From: Matt Fleming 
Date: Sat, 22 Mar 2014 10:09:01 +
Subject: [PATCH] efi: Abstract x86 efi_early calls

The ARM EFI boot stub doesn't need to care about the efi_early
infrastructure that x86 requires in order to do mixed mode thunking. So
wrap everything up in an efi_call_early() macro, which saves ARM having
to implement efi_config.

This allows x86 to do the necessary indirect jumps to call whatever
firmware interface is available (native or mixed mode), and at the same
time allows ARM to use the C type system for parameter checking by
implementing efi_early_call() like so,

#define efi_call_early(f, ...)  \
system_table_arg->boottime->f(__VA_ARGS__);

Signed-off-by: Matt Fleming 
---
 arch/x86/boot/compressed/eboot.c   | 155 -
 drivers/firmware/efi/efi-stub-helper.c |  44 +-
 2 files changed, 98 insertions(+), 101 deletions(-)

diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index 5e1ba4fa3f79..1e6146137f8e 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -21,6 +21,9 @@ static efi_system_table_t *sys_table;
 
 static struct efi_config *efi_early;
 
+#define efi_call_early(f, ...) \
+   efi_early->call(efi_early->f, __VA_ARGS__);
+
 #define BOOT_SERVICES(bits)\
 static void setup_boot_services##bits(struct efi_config *c)\
 {  \
@@ -78,8 +81,8 @@ __file_size32(void *__fh, efi_char16_t *filename_16,
}
 
 grow:
-   status = efi_early->call(efi_early->allocate_pool, EFI_LOADER_DATA,
-info_sz, (void **));
+   status = efi_call_early(allocate_pool, EFI_LOADER_DATA,
+   info_sz, (void **));
if (status != EFI_SUCCESS) {
efi_printk(sys_table, "Failed to alloc mem for file info\n");
return status;
@@ -88,12 +91,12 @@ grow:
status = efi_early->call((unsigned long)h->get_info, h, _guid,
 _sz, info);
if (status == EFI_BUFFER_TOO_SMALL) {
-   efi_early->call(efi_early->free_pool, info);
+   efi_call_early(free_pool, info);
goto grow;
}
 
*file_sz = info->file_size;
-   efi_early->call(efi_early->free_pool, info);
+   efi_call_early(free_pool, info);
 
if (status != EFI_SUCCESS)
efi_printk(sys_table, "Failed to get initrd info\n");
@@ -131,8 +134,8 @@ __file_size64(void *__fh, efi_char16_t *filename_16,
}
 
 grow:
-   status = efi_early->call(efi_early->allocate_pool, EFI_LOADER_DATA,
-info_sz, (void **));
+   status = efi_call_early(allocate_pool, EFI_LOADER_DATA,
+   info_sz, (void **));
if (status != EFI_SUCCESS) {
efi_printk(sys_table, "Failed to 

Re: [PATCH v2 06/13] x86/efi: Build our own EFI services pointer table

2014-03-22 Thread Matt Fleming
On Fri, 21 Mar, at 05:52:29PM, Roy Franz wrote:
 
 For both arm32 and arm64 the Linux and EFI calling conventions are the
 same, so we are directly invoking the function pointers in the
 boot_services table.  This gives us type checking of those calls,
 which is nice.The efi_call_physN macros for ARM are currently simply:
 #define efi_call_phys2(f, a1, a2)f(a1, a2)
 
 With the changes in this patch, we can't do this anymore, as we were
 relying on some macro processing to handle this differently on ARM.

But on the plus side, you no longer have to implement all those
efi_call_physX() macros ;-)

 I'd like to propose something like for following (my variadic macros
 may not be quite right)
 
 for x86:
 #define efi_call_early(...) efi_early-call(__VA_ARGS__)
 
 for arm it would be:
 #define efi_call_early(function, ...) efi_early-function(__VA_ARGS__)

Close enough.

 This would allow us to define the efi_config struct with typed
 function pointers for ARM, and retain the direct invocation along with
 type checking.  This returns to using a macro, but I think we should
 be able to use a variadic macro instead of the 6 separate macros we
 had before.
 
 I plan to use the above technique to incorporate these changes into
 arm64/arm32, barring any better ideas or objections.

Actually, this should be enough to fix this up on ARM,

#define efi_call_early(f, ...)  \
sys_table_arg-boottime-f(__VA_ARGS__);

Then you don't need any of the efi_config stuff.

Yes, the fact that we're making use of the sys_table_arg is invisible at
the call-site, but meh. Not sure that's a big deal. It allows us to use
efi_call_early() in the x86 code without needlessly passing 'sys_table'
around, since we've got a global pointer to it anyhow.

-- 8 --

From 5fcc1036d143802e321a745b2c3d793ddb8369ac Mon Sep 17 00:00:00 2001
From: Matt Fleming matt.flem...@intel.com
Date: Sat, 22 Mar 2014 10:09:01 +
Subject: [PATCH] efi: Abstract x86 efi_early calls

The ARM EFI boot stub doesn't need to care about the efi_early
infrastructure that x86 requires in order to do mixed mode thunking. So
wrap everything up in an efi_call_early() macro, which saves ARM having
to implement efi_config.

This allows x86 to do the necessary indirect jumps to call whatever
firmware interface is available (native or mixed mode), and at the same
time allows ARM to use the C type system for parameter checking by
implementing efi_early_call() like so,

#define efi_call_early(f, ...)  \
system_table_arg-boottime-f(__VA_ARGS__);

Signed-off-by: Matt Fleming matt.flem...@intel.com
---
 arch/x86/boot/compressed/eboot.c   | 155 -
 drivers/firmware/efi/efi-stub-helper.c |  44 +-
 2 files changed, 98 insertions(+), 101 deletions(-)

diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index 5e1ba4fa3f79..1e6146137f8e 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -21,6 +21,9 @@ static efi_system_table_t *sys_table;
 
 static struct efi_config *efi_early;
 
+#define efi_call_early(f, ...) \
+   efi_early-call(efi_early-f, __VA_ARGS__);
+
 #define BOOT_SERVICES(bits)\
 static void setup_boot_services##bits(struct efi_config *c)\
 {  \
@@ -78,8 +81,8 @@ __file_size32(void *__fh, efi_char16_t *filename_16,
}
 
 grow:
-   status = efi_early-call(efi_early-allocate_pool, EFI_LOADER_DATA,
-info_sz, (void **)info);
+   status = efi_call_early(allocate_pool, EFI_LOADER_DATA,
+   info_sz, (void **)info);
if (status != EFI_SUCCESS) {
efi_printk(sys_table, Failed to alloc mem for file info\n);
return status;
@@ -88,12 +91,12 @@ grow:
status = efi_early-call((unsigned long)h-get_info, h, info_guid,
 info_sz, info);
if (status == EFI_BUFFER_TOO_SMALL) {
-   efi_early-call(efi_early-free_pool, info);
+   efi_call_early(free_pool, info);
goto grow;
}
 
*file_sz = info-file_size;
-   efi_early-call(efi_early-free_pool, info);
+   efi_call_early(free_pool, info);
 
if (status != EFI_SUCCESS)
efi_printk(sys_table, Failed to get initrd info\n);
@@ -131,8 +134,8 @@ __file_size64(void *__fh, efi_char16_t *filename_16,
}
 
 grow:
-   status = efi_early-call(efi_early-allocate_pool, EFI_LOADER_DATA,
-info_sz, (void **)info);
+   status = efi_call_early(allocate_pool, EFI_LOADER_DATA,
+   info_sz, (void **)info);
if (status != EFI_SUCCESS) {

Re: [PATCH v2 06/13] x86/efi: Build our own EFI services pointer table

2014-03-22 Thread Roy Franz
On Sat, Mar 22, 2014 at 4:05 AM, Matt Fleming m...@console-pimps.org wrote:
 On Fri, 21 Mar, at 05:52:29PM, Roy Franz wrote:

 For both arm32 and arm64 the Linux and EFI calling conventions are the
 same, so we are directly invoking the function pointers in the
 boot_services table.  This gives us type checking of those calls,
 which is nice.The efi_call_physN macros for ARM are currently simply:
 #define efi_call_phys2(f, a1, a2)f(a1, a2)

 With the changes in this patch, we can't do this anymore, as we were
 relying on some macro processing to handle this differently on ARM.

 But on the plus side, you no longer have to implement all those
 efi_call_physX() macros ;-)

 I'd like to propose something like for following (my variadic macros
 may not be quite right)

 for x86:
 #define efi_call_early(...) efi_early-call(__VA_ARGS__)

 for arm it would be:
 #define efi_call_early(function, ...) efi_early-function(__VA_ARGS__)

 Close enough.

 This would allow us to define the efi_config struct with typed
 function pointers for ARM, and retain the direct invocation along with
 type checking.  This returns to using a macro, but I think we should
 be able to use a variadic macro instead of the 6 separate macros we
 had before.

 I plan to use the above technique to incorporate these changes into
 arm64/arm32, barring any better ideas or objections.

 Actually, this should be enough to fix this up on ARM,

 #define efi_call_early(f, ...)  \
 sys_table_arg-boottime-f(__VA_ARGS__);

 Then you don't need any of the efi_config stuff.

Even better.  I had overlooked that the efi_config variables had identical names
as the boot services.

 Yes, the fact that we're making use of the sys_table_arg is invisible at
 the call-site, but meh. Not sure that's a big deal. It allows us to use
 efi_call_early() in the x86 code without needlessly passing 'sys_table'
 around, since we've got a global pointer to it anyhow.

 -- 8 --

 From 5fcc1036d143802e321a745b2c3d793ddb8369ac Mon Sep 17 00:00:00 2001
 From: Matt Fleming matt.flem...@intel.com
 Date: Sat, 22 Mar 2014 10:09:01 +
 Subject: [PATCH] efi: Abstract x86 efi_early calls

 The ARM EFI boot stub doesn't need to care about the efi_early
 infrastructure that x86 requires in order to do mixed mode thunking. So
 wrap everything up in an efi_call_early() macro, which saves ARM having
 to implement efi_config.

 This allows x86 to do the necessary indirect jumps to call whatever
 firmware interface is available (native or mixed mode), and at the same
 time allows ARM to use the C type system for parameter checking by
 implementing efi_early_call() like so,

 #define efi_call_early(f, ...)  \
 system_table_arg-boottime-f(__VA_ARGS__);

 Signed-off-by: Matt Fleming matt.flem...@intel.com
 ---
  arch/x86/boot/compressed/eboot.c   | 155 
 -
  drivers/firmware/efi/efi-stub-helper.c |  44 +-
  2 files changed, 98 insertions(+), 101 deletions(-)

 diff --git a/arch/x86/boot/compressed/eboot.c 
 b/arch/x86/boot/compressed/eboot.c
 index 5e1ba4fa3f79..1e6146137f8e 100644
 --- a/arch/x86/boot/compressed/eboot.c
 +++ b/arch/x86/boot/compressed/eboot.c
 @@ -21,6 +21,9 @@ static efi_system_table_t *sys_table;

  static struct efi_config *efi_early;

 +#define efi_call_early(f, ...) \
 +   efi_early-call(efi_early-f, __VA_ARGS__);
 +
  #define BOOT_SERVICES(bits)\
  static void setup_boot_services##bits(struct efi_config *c)\
  {  \
 @@ -78,8 +81,8 @@ __file_size32(void *__fh, efi_char16_t *filename_16,
 }

  grow:
 -   status = efi_early-call(efi_early-allocate_pool, EFI_LOADER_DATA,
 -info_sz, (void **)info);
 +   status = efi_call_early(allocate_pool, EFI_LOADER_DATA,
 +   info_sz, (void **)info);
 if (status != EFI_SUCCESS) {
 efi_printk(sys_table, Failed to alloc mem for file info\n);
 return status;
 @@ -88,12 +91,12 @@ grow:
 status = efi_early-call((unsigned long)h-get_info, h, info_guid,
  info_sz, info);
 if (status == EFI_BUFFER_TOO_SMALL) {
 -   efi_early-call(efi_early-free_pool, info);
 +   efi_call_early(free_pool, info);
 goto grow;
 }

 *file_sz = info-file_size;
 -   efi_early-call(efi_early-free_pool, info);
 +   efi_call_early(free_pool, info);

 if (status != EFI_SUCCESS)
 efi_printk(sys_table, Failed to get initrd info\n);
 @@ -131,8 +134,8 @@ __file_size64(void *__fh, efi_char16_t *filename_16,
 }

  grow:
 -   status = efi_early-call(efi_early-allocate_pool, EFI_LOADER_DATA,
 -  

Re: [PATCH v2 06/13] x86/efi: Build our own EFI services pointer table

2014-03-21 Thread Roy Franz
On Tue, Mar 4, 2014 at 5:14 AM, Matt Fleming  wrote:
> From: Matt Fleming 
>
> It's not possible to dereference the EFI System table directly when
> booting a 64-bit kernel on a 32-bit EFI firmware because the size of
> pointers don't match.
>
> In preparation for supporting the above use case, build a list of
> function pointers on boot so that callers don't have to worry about
> converting pointer sizes through multiple levels of indirection.
>
> Signed-off-by: Matt Fleming 
> ---
>  arch/x86/boot/compressed/eboot.c   | 319 
> -
>  arch/x86/boot/compressed/eboot.h   |  16 ++
>  arch/x86/boot/compressed/head_32.S |  48 -
>  arch/x86/boot/compressed/head_64.S |  57 --
>  drivers/firmware/efi/efi-stub-helper.c | 148 ---
>  5 files changed, 377 insertions(+), 211 deletions(-)
>
> diff --git a/arch/x86/boot/compressed/eboot.c 
> b/arch/x86/boot/compressed/eboot.c
> index a7677babf946..42548168bdc3 100644
> --- a/arch/x86/boot/compressed/eboot.c
> +++ b/arch/x86/boot/compressed/eboot.c
> @@ -19,10 +19,145 @@
>
>  static efi_system_table_t *sys_table;
>
> +static struct efi_config *efi_early;
> +
> +#define BOOT_SERVICES(bits)\
> +static void setup_boot_services##bits(struct efi_config *c)\
> +{  \
> +   efi_system_table_##bits##_t *table; \
> +   efi_boot_services_##bits##_t *bt;   \
> +   \
> +   table = (typeof(table))sys_table;   \
> +   \
> +   c->text_output = table->con_out;\
> +   \
> +   bt = (typeof(bt))(unsigned long)(table->boottime);  \
> +   \
> +   c->allocate_pool = bt->allocate_pool;   \
> +   c->allocate_pages = bt->allocate_pages; \
> +   c->get_memory_map = bt->get_memory_map; \
> +   c->free_pool = bt->free_pool;   \
> +   c->free_pages = bt->free_pages; \
> +   c->locate_handle = bt->locate_handle;   \
> +   c->handle_protocol = bt->handle_protocol;   \
> +   c->exit_boot_services = bt->exit_boot_services; \
> +}
> +BOOT_SERVICES(32);
> +BOOT_SERVICES(64);
>
> -#include "../../../../drivers/firmware/efi/efi-stub-helper.c"
> +static void efi_printk(efi_system_table_t *, char *);
> +static void efi_char16_printk(efi_system_table_t *, efi_char16_t *);
> +
> +static efi_status_t
> +efi_file_size(efi_system_table_t *sys_table, void *__fh,
> + efi_char16_t *filename_16, void **handle, u64 *file_sz)
> +{
> +   efi_file_handle_t *h, *fh = __fh;
> +   efi_file_info_t *info;
> +   efi_status_t status;
> +   efi_guid_t info_guid = EFI_FILE_INFO_ID;
> +   u32 info_sz;
> +
> +   status = efi_early->call((unsigned long)fh->open, fh, , filename_16,
> +EFI_FILE_MODE_READ, (u64)0);
> +   if (status != EFI_SUCCESS) {
> +   efi_printk(sys_table, "Failed to open file: ");
> +   efi_char16_printk(sys_table, filename_16);
> +   efi_printk(sys_table, "\n");
> +   return status;
> +   }
> +
> +   *handle = h;
> +
> +   info_sz = 0;
> +   status = efi_early->call((unsigned long)h->get_info, h, _guid,
> +_sz, NULL);
> +   if (status != EFI_BUFFER_TOO_SMALL) {
> +   efi_printk(sys_table, "Failed to get file info size\n");
> +   return status;
> +   }
> +
> +grow:
> +   status = efi_early->call(efi_early->allocate_pool, EFI_LOADER_DATA,
> +info_sz, (void **));
> +   if (status != EFI_SUCCESS) {
> +   efi_printk(sys_table, "Failed to alloc mem for file info\n");
> +   return status;
> +   }
> +
> +   status = efi_early->call((unsigned long)h->get_info, h, _guid,
> +_sz, info);
> +   if (status == EFI_BUFFER_TOO_SMALL) {
> +   efi_early->call(efi_early->free_pool, info);
> +   goto grow;
> +   }
> +
> +   *file_sz = info->file_size;
> +   efi_early->call(efi_early->free_pool, info);
> +
> +   if (status != EFI_SUCCESS)
> +   efi_printk(sys_table, "Failed to get initrd info\n");
> +
> +   return status;
> +}
> +
> +static inline efi_status_t
> +efi_file_read(void *__fh, void *handle, unsigned long *size, void *addr)
> +{
> +   

Re: [PATCH v2 06/13] x86/efi: Build our own EFI services pointer table

2014-03-21 Thread Roy Franz
On Tue, Mar 4, 2014 at 5:14 AM, Matt Fleming m...@console-pimps.org wrote:
 From: Matt Fleming matt.flem...@intel.com

 It's not possible to dereference the EFI System table directly when
 booting a 64-bit kernel on a 32-bit EFI firmware because the size of
 pointers don't match.

 In preparation for supporting the above use case, build a list of
 function pointers on boot so that callers don't have to worry about
 converting pointer sizes through multiple levels of indirection.

 Signed-off-by: Matt Fleming matt.flem...@intel.com
 ---
  arch/x86/boot/compressed/eboot.c   | 319 
 -
  arch/x86/boot/compressed/eboot.h   |  16 ++
  arch/x86/boot/compressed/head_32.S |  48 -
  arch/x86/boot/compressed/head_64.S |  57 --
  drivers/firmware/efi/efi-stub-helper.c | 148 ---
  5 files changed, 377 insertions(+), 211 deletions(-)

 diff --git a/arch/x86/boot/compressed/eboot.c 
 b/arch/x86/boot/compressed/eboot.c
 index a7677babf946..42548168bdc3 100644
 --- a/arch/x86/boot/compressed/eboot.c
 +++ b/arch/x86/boot/compressed/eboot.c
 @@ -19,10 +19,145 @@

  static efi_system_table_t *sys_table;

 +static struct efi_config *efi_early;
 +
 +#define BOOT_SERVICES(bits)\
 +static void setup_boot_services##bits(struct efi_config *c)\
 +{  \
 +   efi_system_table_##bits##_t *table; \
 +   efi_boot_services_##bits##_t *bt;   \
 +   \
 +   table = (typeof(table))sys_table;   \
 +   \
 +   c-text_output = table-con_out;\
 +   \
 +   bt = (typeof(bt))(unsigned long)(table-boottime);  \
 +   \
 +   c-allocate_pool = bt-allocate_pool;   \
 +   c-allocate_pages = bt-allocate_pages; \
 +   c-get_memory_map = bt-get_memory_map; \
 +   c-free_pool = bt-free_pool;   \
 +   c-free_pages = bt-free_pages; \
 +   c-locate_handle = bt-locate_handle;   \
 +   c-handle_protocol = bt-handle_protocol;   \
 +   c-exit_boot_services = bt-exit_boot_services; \
 +}
 +BOOT_SERVICES(32);
 +BOOT_SERVICES(64);

 -#include ../../../../drivers/firmware/efi/efi-stub-helper.c
 +static void efi_printk(efi_system_table_t *, char *);
 +static void efi_char16_printk(efi_system_table_t *, efi_char16_t *);
 +
 +static efi_status_t
 +efi_file_size(efi_system_table_t *sys_table, void *__fh,
 + efi_char16_t *filename_16, void **handle, u64 *file_sz)
 +{
 +   efi_file_handle_t *h, *fh = __fh;
 +   efi_file_info_t *info;
 +   efi_status_t status;
 +   efi_guid_t info_guid = EFI_FILE_INFO_ID;
 +   u32 info_sz;
 +
 +   status = efi_early-call((unsigned long)fh-open, fh, h, filename_16,
 +EFI_FILE_MODE_READ, (u64)0);
 +   if (status != EFI_SUCCESS) {
 +   efi_printk(sys_table, Failed to open file: );
 +   efi_char16_printk(sys_table, filename_16);
 +   efi_printk(sys_table, \n);
 +   return status;
 +   }
 +
 +   *handle = h;
 +
 +   info_sz = 0;
 +   status = efi_early-call((unsigned long)h-get_info, h, info_guid,
 +info_sz, NULL);
 +   if (status != EFI_BUFFER_TOO_SMALL) {
 +   efi_printk(sys_table, Failed to get file info size\n);
 +   return status;
 +   }
 +
 +grow:
 +   status = efi_early-call(efi_early-allocate_pool, EFI_LOADER_DATA,
 +info_sz, (void **)info);
 +   if (status != EFI_SUCCESS) {
 +   efi_printk(sys_table, Failed to alloc mem for file info\n);
 +   return status;
 +   }
 +
 +   status = efi_early-call((unsigned long)h-get_info, h, info_guid,
 +info_sz, info);
 +   if (status == EFI_BUFFER_TOO_SMALL) {
 +   efi_early-call(efi_early-free_pool, info);
 +   goto grow;
 +   }
 +
 +   *file_sz = info-file_size;
 +   efi_early-call(efi_early-free_pool, info);
 +
 +   if (status != EFI_SUCCESS)
 +   efi_printk(sys_table, Failed to get initrd info\n);
 +
 +   return status;
 +}
 +
 +static inline efi_status_t
 +efi_file_read(void *__fh, void *handle, unsigned long *size, void *addr)
 +{
 +   efi_file_handle_t *fh = __fh;
 +   return efi_early-call((unsigned 

[PATCH v2 06/13] x86/efi: Build our own EFI services pointer table

2014-03-04 Thread Matt Fleming
From: Matt Fleming 

It's not possible to dereference the EFI System table directly when
booting a 64-bit kernel on a 32-bit EFI firmware because the size of
pointers don't match.

In preparation for supporting the above use case, build a list of
function pointers on boot so that callers don't have to worry about
converting pointer sizes through multiple levels of indirection.

Signed-off-by: Matt Fleming 
---
 arch/x86/boot/compressed/eboot.c   | 319 -
 arch/x86/boot/compressed/eboot.h   |  16 ++
 arch/x86/boot/compressed/head_32.S |  48 -
 arch/x86/boot/compressed/head_64.S |  57 --
 drivers/firmware/efi/efi-stub-helper.c | 148 ---
 5 files changed, 377 insertions(+), 211 deletions(-)

diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index a7677babf946..42548168bdc3 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -19,10 +19,145 @@
 
 static efi_system_table_t *sys_table;
 
+static struct efi_config *efi_early;
+
+#define BOOT_SERVICES(bits)\
+static void setup_boot_services##bits(struct efi_config *c)\
+{  \
+   efi_system_table_##bits##_t *table; \
+   efi_boot_services_##bits##_t *bt;   \
+   \
+   table = (typeof(table))sys_table;   \
+   \
+   c->text_output = table->con_out;\
+   \
+   bt = (typeof(bt))(unsigned long)(table->boottime);  \
+   \
+   c->allocate_pool = bt->allocate_pool;   \
+   c->allocate_pages = bt->allocate_pages; \
+   c->get_memory_map = bt->get_memory_map; \
+   c->free_pool = bt->free_pool;   \
+   c->free_pages = bt->free_pages; \
+   c->locate_handle = bt->locate_handle;   \
+   c->handle_protocol = bt->handle_protocol;   \
+   c->exit_boot_services = bt->exit_boot_services; \
+}
+BOOT_SERVICES(32);
+BOOT_SERVICES(64);
 
-#include "../../../../drivers/firmware/efi/efi-stub-helper.c"
+static void efi_printk(efi_system_table_t *, char *);
+static void efi_char16_printk(efi_system_table_t *, efi_char16_t *);
+
+static efi_status_t
+efi_file_size(efi_system_table_t *sys_table, void *__fh,
+ efi_char16_t *filename_16, void **handle, u64 *file_sz)
+{
+   efi_file_handle_t *h, *fh = __fh;
+   efi_file_info_t *info;
+   efi_status_t status;
+   efi_guid_t info_guid = EFI_FILE_INFO_ID;
+   u32 info_sz;
+
+   status = efi_early->call((unsigned long)fh->open, fh, , filename_16,
+EFI_FILE_MODE_READ, (u64)0);
+   if (status != EFI_SUCCESS) {
+   efi_printk(sys_table, "Failed to open file: ");
+   efi_char16_printk(sys_table, filename_16);
+   efi_printk(sys_table, "\n");
+   return status;
+   }
+
+   *handle = h;
+
+   info_sz = 0;
+   status = efi_early->call((unsigned long)h->get_info, h, _guid,
+_sz, NULL);
+   if (status != EFI_BUFFER_TOO_SMALL) {
+   efi_printk(sys_table, "Failed to get file info size\n");
+   return status;
+   }
+
+grow:
+   status = efi_early->call(efi_early->allocate_pool, EFI_LOADER_DATA,
+info_sz, (void **));
+   if (status != EFI_SUCCESS) {
+   efi_printk(sys_table, "Failed to alloc mem for file info\n");
+   return status;
+   }
+
+   status = efi_early->call((unsigned long)h->get_info, h, _guid,
+_sz, info);
+   if (status == EFI_BUFFER_TOO_SMALL) {
+   efi_early->call(efi_early->free_pool, info);
+   goto grow;
+   }
+
+   *file_sz = info->file_size;
+   efi_early->call(efi_early->free_pool, info);
+
+   if (status != EFI_SUCCESS)
+   efi_printk(sys_table, "Failed to get initrd info\n");
+
+   return status;
+}
+
+static inline efi_status_t
+efi_file_read(void *__fh, void *handle, unsigned long *size, void *addr)
+{
+   efi_file_handle_t *fh = __fh;
+   return efi_early->call((unsigned long)fh->read, handle, size, addr);
+}
+
+static inline efi_status_t efi_file_close(void *__fh, void *handle)
+{
+   efi_file_handle_t *fh = __fh;
 
+   return efi_early->call((unsigned long)fh->close, 

[PATCH v2 06/13] x86/efi: Build our own EFI services pointer table

2014-03-04 Thread Matt Fleming
From: Matt Fleming matt.flem...@intel.com

It's not possible to dereference the EFI System table directly when
booting a 64-bit kernel on a 32-bit EFI firmware because the size of
pointers don't match.

In preparation for supporting the above use case, build a list of
function pointers on boot so that callers don't have to worry about
converting pointer sizes through multiple levels of indirection.

Signed-off-by: Matt Fleming matt.flem...@intel.com
---
 arch/x86/boot/compressed/eboot.c   | 319 -
 arch/x86/boot/compressed/eboot.h   |  16 ++
 arch/x86/boot/compressed/head_32.S |  48 -
 arch/x86/boot/compressed/head_64.S |  57 --
 drivers/firmware/efi/efi-stub-helper.c | 148 ---
 5 files changed, 377 insertions(+), 211 deletions(-)

diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index a7677babf946..42548168bdc3 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -19,10 +19,145 @@
 
 static efi_system_table_t *sys_table;
 
+static struct efi_config *efi_early;
+
+#define BOOT_SERVICES(bits)\
+static void setup_boot_services##bits(struct efi_config *c)\
+{  \
+   efi_system_table_##bits##_t *table; \
+   efi_boot_services_##bits##_t *bt;   \
+   \
+   table = (typeof(table))sys_table;   \
+   \
+   c-text_output = table-con_out;\
+   \
+   bt = (typeof(bt))(unsigned long)(table-boottime);  \
+   \
+   c-allocate_pool = bt-allocate_pool;   \
+   c-allocate_pages = bt-allocate_pages; \
+   c-get_memory_map = bt-get_memory_map; \
+   c-free_pool = bt-free_pool;   \
+   c-free_pages = bt-free_pages; \
+   c-locate_handle = bt-locate_handle;   \
+   c-handle_protocol = bt-handle_protocol;   \
+   c-exit_boot_services = bt-exit_boot_services; \
+}
+BOOT_SERVICES(32);
+BOOT_SERVICES(64);
 
-#include ../../../../drivers/firmware/efi/efi-stub-helper.c
+static void efi_printk(efi_system_table_t *, char *);
+static void efi_char16_printk(efi_system_table_t *, efi_char16_t *);
+
+static efi_status_t
+efi_file_size(efi_system_table_t *sys_table, void *__fh,
+ efi_char16_t *filename_16, void **handle, u64 *file_sz)
+{
+   efi_file_handle_t *h, *fh = __fh;
+   efi_file_info_t *info;
+   efi_status_t status;
+   efi_guid_t info_guid = EFI_FILE_INFO_ID;
+   u32 info_sz;
+
+   status = efi_early-call((unsigned long)fh-open, fh, h, filename_16,
+EFI_FILE_MODE_READ, (u64)0);
+   if (status != EFI_SUCCESS) {
+   efi_printk(sys_table, Failed to open file: );
+   efi_char16_printk(sys_table, filename_16);
+   efi_printk(sys_table, \n);
+   return status;
+   }
+
+   *handle = h;
+
+   info_sz = 0;
+   status = efi_early-call((unsigned long)h-get_info, h, info_guid,
+info_sz, NULL);
+   if (status != EFI_BUFFER_TOO_SMALL) {
+   efi_printk(sys_table, Failed to get file info size\n);
+   return status;
+   }
+
+grow:
+   status = efi_early-call(efi_early-allocate_pool, EFI_LOADER_DATA,
+info_sz, (void **)info);
+   if (status != EFI_SUCCESS) {
+   efi_printk(sys_table, Failed to alloc mem for file info\n);
+   return status;
+   }
+
+   status = efi_early-call((unsigned long)h-get_info, h, info_guid,
+info_sz, info);
+   if (status == EFI_BUFFER_TOO_SMALL) {
+   efi_early-call(efi_early-free_pool, info);
+   goto grow;
+   }
+
+   *file_sz = info-file_size;
+   efi_early-call(efi_early-free_pool, info);
+
+   if (status != EFI_SUCCESS)
+   efi_printk(sys_table, Failed to get initrd info\n);
+
+   return status;
+}
+
+static inline efi_status_t
+efi_file_read(void *__fh, void *handle, unsigned long *size, void *addr)
+{
+   efi_file_handle_t *fh = __fh;
+   return efi_early-call((unsigned long)fh-read, handle, size, addr);
+}
+
+static inline efi_status_t efi_file_close(void *__fh, void *handle)
+{
+   efi_file_handle_t *fh = __fh;
 
+   return efi_early-call((unsigned