All of lore.kernel.org
 help / color / mirror / Atom feed
From: Alexander Graf <agraf@suse.de>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH 09/14] efi_loader: Implement memory allocation and map
Date: Tue, 2 Feb 2016 01:59:58 +0100	[thread overview]
Message-ID: <56AFFF8E.4010501@suse.de> (raw)
In-Reply-To: <CAPnjgZ0YN10PD4o=WbAF-aCjJyHAZfMigGk=47ofg9-JnOyodQ@mail.gmail.com>



On 01/31/2016 04:23 PM, Simon Glass wrote:
> Hi Alexander,
>
> On 14 January 2016 at 22:06, Alexander Graf <agraf@suse.de> wrote:
>> Due to popular request, this is a separate patch implementing all of the memory
>> allocation and memory mapping bits.
>>
>> We assume we always have a linear RAM map. At TOM U-Boot resides. Inside of
>> U-Boot there is the runtime region that we need to explicitly expose via the
>> EFI memory map. Below U-Boot, we reserve 128MB of RAM for LOADER_DATA.
>>
>> Signed-off-by: Alexander Graf <agraf@suse.de>
>> ---
>>   lib/efi_loader/efi_boottime.c     | 99 ++++++++++++++++++++++++++++++++++++++-
>>   lib/efi_loader/efi_image_loader.c | 28 ++++++++++-
>>   2 files changed, 123 insertions(+), 4 deletions(-)
>>
>> diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
>> index 45217ef..ff3f969 100644
>> --- a/lib/efi_loader/efi_boottime.c
>> +++ b/lib/efi_loader/efi_boottime.c
>> @@ -98,6 +98,8 @@ static void efi_restore_tpl(unsigned long old_tpl)
>>   static void *efi_alloc(uint64_t len, int memory_type)
>>   {
>>          switch (memory_type) {
>> +       case EFI_LOADER_DATA:
>> +               return efi_loader_alloc(len);
>>          default:
>>                  return malloc(len);
>>          }
>> @@ -143,16 +145,109 @@ static efi_status_t efi_free_pages(uint64_t memory, unsigned long pages)
>>          return EFI_EXIT(EFI_SUCCESS);
>>   }
>>
>> -/* Will be implemented in a later patch */
>> +/*
>> + * Returns the EFI memory map. In our case, this looks pretty simple:
>> + *
>> + *  ____________________________    TOM
>> + * |                            |
>> + * |    Second half of U-Boot   |
> What does 'second half' mean?

It means that there's one big chunk of "U-Boot" with the RTS sitting in 
the middle, dividing it into 2 halves :).

I hope my new memory allocation code makes this more obvious.

>
>> + * |____________________________|   &__efi_runtime_stop
>> + * |                            |
>> + * |    EFI Runtime Services    |
>> + * |____________________________|   &__efi_runtime_start
>> + * |                            |
>> + * |    First half of U-Boot    |
>> + * |____________________________|   start of EFI loader allocation space
>> + * |                            |
>> + * |          Free RAM          |
>> + * |____________________________|   CONFIG_SYS_SDRAM_BASE
>> + *
>> + * All pointers are extended to live on a 4k boundary. After exiting the boot
>> + * services, only the EFI Runtime Services chunk of memory stays alive.
>> + */
>>   static efi_status_t efi_get_memory_map(unsigned long *memory_map_size,
>>                                 struct efi_mem_desc *memory_map,
>>                                 unsigned long *map_key,
>>                                 unsigned long *descriptor_size,
>>                                 uint32_t *descriptor_version)
>>   {
>> +       struct efi_mem_desc efi_memory_map[] = {
>> +               {
>> +                       /* RAM before U-Boot */
>> +                       .type = EFI_CONVENTIONAL_MEMORY,
>> +                       .attribute = 1 << EFI_MEMORY_WB_SHIFT,
>> +               },
>> +               {
>> +                       /* First half of U-Boot */
>> +                       .type = EFI_LOADER_DATA,
>> +                       .attribute = 1 << EFI_MEMORY_WB_SHIFT,
>> +               },
>> +               {
>> +                       /* EFI Runtime Services */
>> +                       .type = EFI_RUNTIME_SERVICES_CODE,
>> +                       .attribute = (1 << EFI_MEMORY_WB_SHIFT) |
>> +                                    (1ULL << EFI_MEMORY_RUNTIME_SHIFT),
>> +               },
>> +               {
>> +                       /* Second half of U-Boot */
>> +                       .type = EFI_LOADER_DATA,
>> +                       .attribute = 1 << EFI_MEMORY_WB_SHIFT,
>> +               },
>> +       };
>> +       ulong runtime_start, runtime_end, runtime_len_pages, runtime_len;
>> +
>>          EFI_ENTRY("%p, %p, %p, %p, %p", memory_map_size, memory_map, map_key,
>>                    descriptor_size, descriptor_version);
>> -       return EFI_EXIT(EFI_UNSUPPORTED);
>> +
>> +       runtime_start = (ulong)&__efi_runtime_start & ~0xfffULL;
>> +       runtime_end = ((ulong)&__efi_runtime_stop + 0xfff) & ~0xfffULL;
>> +       runtime_len_pages = (runtime_end - runtime_start) >> 12;
>> +       runtime_len = runtime_len_pages << 12;
>> +
>> +       /* Fill in where normal RAM is (up to U-Boot's top of stack) */
>> +       efi_memory_map[0].num_pages = gd->start_addr_sp >> 12;
>> +#ifdef CONFIG_SYS_SDRAM_BASE
> If not defined, what happens?

The new code uses gd->bd->bi_dram.

>
>> +       efi_memory_map[0].physical_start = CONFIG_SYS_SDRAM_BASE;
>> +       efi_memory_map[0].virtual_start = CONFIG_SYS_SDRAM_BASE;
>> +       efi_memory_map[0].num_pages -= CONFIG_SYS_SDRAM_BASE >> 12;
>> +#endif
>> +
>> +       /* Give us some space for the stack */
>> +       efi_memory_map[0].num_pages -= (16 * 1024 * 1024) >> 12;
>> +
>> +       /* Reserve the EFI loader pool */
>> +       efi_memory_map[0].num_pages -= EFI_LOADER_POOL_SIZE >> 12;
>> +
>> +       /* Cut out the runtime services */
>> +       efi_memory_map[2].physical_start = runtime_start;
>> +       efi_memory_map[2].virtual_start = efi_memory_map[2].physical_start;
>> +       efi_memory_map[2].num_pages = runtime_len_pages;
>> +
>> +       /* Allocate the rest to U-Boot */
>> +       efi_memory_map[1].physical_start = efi_memory_map[0].physical_start +
>> +                                          (efi_memory_map[0].num_pages << 12);
>> +       efi_memory_map[1].virtual_start = efi_memory_map[1].physical_start;
>> +       efi_memory_map[1].num_pages = (runtime_start -
>> +                                      efi_memory_map[1].physical_start) >> 12;
>> +
>> +       efi_memory_map[3].physical_start = runtime_start + runtime_len;
>> +       efi_memory_map[3].virtual_start = efi_memory_map[3].physical_start;
>> +       efi_memory_map[3].num_pages = (gd->ram_top -
>> +                                      efi_memory_map[3].physical_start) >> 12;
>> +
>> +       *memory_map_size = sizeof(efi_memory_map);
>> +
>> +       if (descriptor_size)
>> +               *descriptor_size = sizeof(struct efi_mem_desc);
>> +
>> +       if (*memory_map_size < sizeof(efi_memory_map)) {
>> +               return EFI_EXIT(EFI_BUFFER_TOO_SMALL);
>> +       }
>> +
>> +       if (memory_map)
>> +               memcpy(memory_map, efi_memory_map, sizeof(efi_memory_map));
>> +
>> +       return EFI_EXIT(EFI_SUCCESS);
>>   }
>>
>>   static efi_status_t efi_allocate_pool(int pool_type, unsigned long size, void **buffer)
>> diff --git a/lib/efi_loader/efi_image_loader.c b/lib/efi_loader/efi_image_loader.c
>> index a7788bf..67c4b06 100644
>> --- a/lib/efi_loader/efi_image_loader.c
>> +++ b/lib/efi_loader/efi_image_loader.c
>> @@ -29,10 +29,34 @@ efi_status_t efi_return_handle(void *handle, efi_guid_t *protocol,
>>          return EFI_SUCCESS;
>>   }
>>
>> -/* Will be implemented in a later patch */
>> +/*
>> + * EFI payloads potentially want to load pretty big images into memory,
>> + * so our small malloc region isn't enough for them. However, they usually
>> + * don't need a smart allocator either.
>> + *
>> + * So instead give them a really dumb one. We just reserve EFI_LOADER_POOL_SIZE
>> + * bytes from 16MB below the stack start to give the stack some space.
>> + * Then every allocation gets a 4k aligned chunk from it. We never free.
>> + */
>>   void *efi_loader_alloc(uint64_t len)
>>   {
>> -       return NULL;
>> +       static unsigned long loader_pool;
>> +       void *r;
>> +
>> +       if (!loader_pool) {
>> +               loader_pool = ((gd->start_addr_sp >> 12) << 12) -
>> +                             (16 * MB) - EFI_LOADER_POOL_SIZE;
> I think it would be better to reserve this in board_f() with a
> reserve...() function. Perhaps store the address in global_data.

The new code doesn't reserve anything anymore :)


Alex

>
>> +       }
>> +
>> +       len = ROUND_UP(len, 4096);
>> +       /* Out of memory */
>> +       if ((loader_pool + len) >= (gd->relocaddr - TOTAL_MALLOC_LEN))
> debug() here?
>
>> +               return NULL;
>> +
>> +       r = (void *)loader_pool;
>> +       loader_pool += len;
>> +
>> +       return r;
>>   }
>>
>>   /*
>> --
>> 2.1.4
> Regards,
> Simon

  reply	other threads:[~2016-02-02  0:59 UTC|newest]

Thread overview: 45+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-01-15  5:06 [U-Boot] [PATCH 00/14] EFI payload / application support v2 Alexander Graf
2016-01-15  5:06 ` [U-Boot] [PATCH 01/14] disk/part.c: Expose list of available block drivers Alexander Graf
2016-01-15  5:06 ` [U-Boot] [PATCH 02/14] include/efi_api.h: Add more detailed API definitions Alexander Graf
2016-01-31 15:17   ` Simon Glass
2016-02-01 22:46     ` Alexander Graf
2016-01-15  5:06 ` [U-Boot] [PATCH 03/14] efi_loader: Add PE image loader Alexander Graf
2016-01-31 15:18   ` Simon Glass
2016-02-01 22:58     ` Alexander Graf
2016-01-15  5:06 ` [U-Boot] [PATCH 04/14] efi_loader: Add boot time services Alexander Graf
2016-01-20  0:16   ` Leif Lindholm
2016-02-02  1:52     ` Alexander Graf
2016-01-31 15:19   ` Simon Glass
2016-02-01 23:45     ` Alexander Graf
2016-02-01 23:54       ` Simon Glass
2016-02-02  0:02         ` Alexander Graf
2016-01-15  5:06 ` [U-Boot] [PATCH 05/14] efi_loader: Add console interface Alexander Graf
2016-01-31 15:19   ` Simon Glass
2016-01-15  5:06 ` [U-Boot] [PATCH 06/14] efi_loader: Add runtime services Alexander Graf
2016-01-21 17:20   ` Leif Lindholm
2016-01-31 15:20   ` Simon Glass
2016-02-01 23:57     ` Alexander Graf
2016-01-15  5:06 ` [U-Boot] [PATCH 07/14] efi_loader: Add disk interfaces Alexander Graf
2016-01-31 15:23   ` Simon Glass
2016-02-02  0:32     ` Alexander Graf
2016-01-15  5:06 ` [U-Boot] [PATCH 08/14] efi_loader: Add "bootefi" command Alexander Graf
2016-01-31 15:23   ` Simon Glass
2016-01-15  5:06 ` [U-Boot] [PATCH 09/14] efi_loader: Implement memory allocation and map Alexander Graf
2016-01-31 15:23   ` Simon Glass
2016-02-02  0:59     ` Alexander Graf [this message]
2016-01-15  5:06 ` [U-Boot] [PATCH 10/14] arm64: Allow exceptions to return Alexander Graf
2016-01-15  5:06 ` [U-Boot] [PATCH 11/14] arm64: Allow EFI payload code to take exceptions Alexander Graf
2016-01-15  5:06 ` [U-Boot] [PATCH 12/14] efi_loader: Add DCACHE_OFF support for arm64 Alexander Graf
2016-01-15  5:06 ` [U-Boot] [PATCH 13/14] efi_loader: hook up in build environment Alexander Graf
2016-01-31 15:24   ` Simon Glass
2016-01-15  5:06 ` [U-Boot] [PATCH 14/14] efi_loader: Add distro boot script for removable media Alexander Graf
2016-01-31 15:24   ` Simon Glass
2016-02-02  1:05     ` Alexander Graf
2016-01-31 15:17 ` [U-Boot] [PATCH 00/14] EFI payload / application support v2 Simon Glass
2016-01-31 21:43   ` Alexander Graf
2016-02-01  2:52     ` Simon Glass
2016-02-01  3:25       ` Simon Glass
2016-02-01 21:38       ` Alexander Graf
2016-02-02  0:02         ` Simon Glass
2016-02-02  0:16           ` Alexander Graf
2016-02-02  0:28             ` Simon Glass

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=56AFFF8E.4010501@suse.de \
    --to=agraf@suse.de \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.