blob: a177c08388b99481a91592658098a4e2855478f6 [file]
/*
* Copyright 2020, Data61, CSIRO (ABN 41 687 119 230)
*
* SPDX-License-Identifier: GPL-2.0-only
*/
#include <binaries/efi/efi.h>
#include <elfloader_common.h>
void *__application_handle = NULL; // current efi application handler
efi_system_table_t *__efi_system_table = NULL; // current efi system table
extern void _start(void);
unsigned int efi_main(uintptr_t application_handle, uintptr_t efi_system_table)
{
clear_bss();
__application_handle = (void *)application_handle;
__efi_system_table = (efi_system_table_t *)efi_system_table;
_start();
return 0;
}
void *efi_get_fdt(void)
{
efi_guid_t fdt_guid = make_efi_guid(0xb1b621d5, 0xf19c, 0x41a5, 0x83, 0x0b, 0xd9, 0x15, 0x2c, 0x69, 0xaa, 0xe0);
efi_config_table_t *tables = (efi_config_table_t *)__efi_system_table->tables;
for (uint32_t i = 0; i < __efi_system_table->nr_tables; i++) {
if (!efi_guideq(fdt_guid, tables[i].guid))
continue;
return (void *)tables[i].table;
}
return NULL;
}
/* Before starting the kernel we should notify the UEFI firmware about it
* otherwise the internal watchdog may reboot us after 5 min.
*
* This means boot time services are not available anymore. We should store
* system information e.g. current memory map and pass them to kernel.
*/
unsigned long efi_exit_boot_services(void)
{
unsigned long status;
efi_memory_desc_t *memory_map;
unsigned long map_size;
unsigned long desc_size, key;
uint32_t desc_version;
efi_boot_services_t *bts = get_efi_boot_services();
/*
* As the number of existing memeory segments are unknown,
* we need to resort to a trial and error to guess that.
* We start from 32 and increase it by one until get a valid value.
*/
map_size = sizeof(*memory_map) * 32;
again:
status = bts->allocate_pool(EFI_LOADER_DATA, map_size, (void **)&memory_map);
if (status != EFI_SUCCESS)
return status;
status = bts->get_memory_map(&map_size, memory_map, &key, &desc_size, &desc_version);
if (status == EFI_BUFFER_TOO_SMALL) {
bts->free_pool(memory_map);
map_size += sizeof(*memory_map);
goto again;
}
if (status != EFI_SUCCESS){
bts->free_pool(memory_map);
return status;
}
status = bts->exit_boot_services(__application_handle, key);
return status;
}