|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH RFC 19/19] Add EFI stub for ARM64
On Sat, 2014-06-28 at 02:25 +0100, Roy Franz wrote:
> This patch adds the real EFI application entry point in head.S,
> and adds the efi.c file that will contain the EFI stub implementation.
> The assembly wrapper is responsible for returning the processor state
> to what XEN expects when starting. The EFI stub processes the
> XEN EFI configuration file to load the dom0 kernel, ramdisk, etc and
> constructs a device tree for XEN to use, then transfers control to
> the normal XEN image entry point.
>
> Signed-off-by: Roy Franz <roy.franz@xxxxxxxxxx>
> ---
> xen/arch/arm/Makefile | 2 +
> xen/arch/arm/arm64/head.S | 62 ++++-
> xen/arch/arm/efi-shared.c | 1 +
> xen/arch/arm/efi.c | 686
> ++++++++++++++++++++++++++++++++++++++++++++++
> 4 files changed, 750 insertions(+), 1 deletion(-)
> create mode 120000 xen/arch/arm/efi-shared.c
> create mode 100644 xen/arch/arm/efi.c
>
> diff --git a/xen/arch/arm/Makefile b/xen/arch/arm/Makefile
> index 63e0460..c3ed74f 100644
> --- a/xen/arch/arm/Makefile
> +++ b/xen/arch/arm/Makefile
> @@ -33,6 +33,8 @@ obj-y += hvm.o
> obj-y += device.o
> obj-y += decode.o
> obj-y += processor.o
> +obj-y += efi.o
> +obj-y += efi-shared.o
While the latter will eventually be in xen/common/efi/something.c and
hence -fshort-char is taken care of I suppose efi.o needs it too?
Probably the easiest thing to do there is to create
xen/arch/arm/efi/stub.c and do the fshort-char trick for that entire
folder, since I don't think our build system makes it especially easy to
change CFLAGS for individual object files.
> +
> + /*
> + * efi_entry() will return here with device tree address in x0.
> + * Save value in register which is preserved by __flush_dcache_all.
> + */
> + mov x20, x0
> +
> + /* Turn off Dcache and MMU */
AIUI EFI leaves us in a 1:1 mapping, hence this is safe to do.
> + mrs x0, CurrentEL
> + cmp x0, #PSR_MODE_EL2t
> + ccmp x0, #PSR_MODE_EL2h, #0x4, ne
> + b.ne 1f
> + mrs x0, sctlr_el2
> + bic x0, x0, #1 << 0 // clear SCTLR.M
> + bic x0, x0, #1 << 2 // clear SCTLR.C
> + msr sctlr_el2, x0
> + isb
> + b 2f
> +1:
> + mrs x0, sctlr_el1
I hope there is no way to get here under Xen ;-) I suppose you do it
this way so that we reach the regular head.S which then prints all the
error messages etc?
> + bic x0, x0, #1 << 0 // clear SCTLR.M
> + bic x0, x0, #1 << 2 // clear SCTLR.C
> + msr sctlr_el1, x0
> + isb
> +2:
> +/* bl __flush_dcache_all */ /* RFRANZ_TODO */
We just don't have this function right now, correct? I suppose you are
running on models without cache modelling turned on?
Eventually this will implement a total by set/way, right? That's safe
because we are uniprocessor at this point etc etc.
> +/*
> + * This define and the code associated with it is a temporary, and will
> + * be replaced by changes to the XEN kernel to use the EFI memory map
> + * that is passed in the device tree instead of the normal FDT memory map.
> + * The XEN kernel changes are largely indpendent of the stub, so this code
FWIW given this is totally temporary: "independent".
> + * has been added to allow review and some testing of the stub code while
> + * the XEN kernel code is being developed.
> + */
> +#define ADD_EFI_MEMORY_TO_FDT
> +
> +#define DEVICE_TREE_GUID \
> +{0xb1b621d5, 0xf19c, 0x41a5, {0x83, 0x0b, 0xd9, 0x15, 0x2c, 0x69, 0xaa,
> 0xe0}}
> +
> +extern CHAR16 __initdata newline[];
> +extern SIMPLE_TEXT_OUTPUT_INTERFACE *__initdata StdOut;
> +extern SIMPLE_TEXT_OUTPUT_INTERFACE *__initdata StdERR;
> +extern EFI_BOOT_SERVICES *__initdata efi_bs;
> +
> +
> +static EFI_HANDLE __initdata efi_ih;
> +
> +static struct file __initdata cfg;
> +static struct file __initdata kernel;
> +static struct file __initdata ramdisk;
> +static struct file __initdata dtb;
> +
> +static unsigned long mmap_size;
> +static EFI_MEMORY_DESCRIPTOR *mmap_ptr;
> +
> +static void *new_fdt;
> +
> +#ifdef ADD_EFI_MEMORY_TO_FDT
> +static int IsLinuxReservedRegion(int MemoryType)
Linux? I guess this is a hangover from the Linux stub?
(Even there I'd have thought the regions were reserved by EFI not Linux
though, perhaps I'm looking at it backwards though)
> +{
> + switch ( MemoryType )
> + {
> + case EfiMemoryMappedIO:
> + case EfiMemoryMappedIOPortSpace:
> + case EfiRuntimeServicesCode:
> + case EfiRuntimeServicesData:
> + case EfiUnusableMemory:
> + case EfiACPIReclaimMemory:
> + case EfiACPIMemoryNVS:
> + case EfiLoaderData:
> + return 1;
> + default:
> + return 0;
> + }
> +}
> +
> +
> +static EFI_STATUS __init efi_process_memory_map(EFI_MEMORY_DESCRIPTOR *map,
> + unsigned long mmap_size,
> + unsigned long desc_size,
> + void *fdt)
> +{
> + int Index;
> + int err;
> +
> + EFI_MEMORY_DESCRIPTOR *desc_ptr = map;
> +
> + /* Go through the list and add the reserved region to the Device Tree */
> + for ( Index = 0; Index < (mmap_size / desc_size); Index++ )
> + {
> + if ( IsLinuxReservedRegion(desc_ptr->Type) )
> + {
> + err = fdt_add_mem_rsv(fdt, desc_ptr->PhysicalStart,
> desc_ptr->NumberOfPages * EFI_PAGE_SIZE);
> + if ( err != 0 )
> + PrintStr(L"Warning: Fail to add 'memreserve'\n\n");
> + }
> + desc_ptr = NextMemoryDescriptor(desc_ptr, desc_size);
> + }
> +
> + return EFI_SUCCESS;
> +
> +}
> +#endif
> +
> +static EFI_STATUS __init efi_get_memory_map(EFI_SYSTEM_TABLE *sys_table_arg,
> + EFI_MEMORY_DESCRIPTOR **map,
> + unsigned long *mmap_size,
> + unsigned long *desc_size,
> + UINT32 *desc_ver,
> + unsigned long *key_ptr)
> +{
> + EFI_MEMORY_DESCRIPTOR *m = NULL;
> + EFI_STATUS status;
> + unsigned long key;
> + u32 desc_version;
> +
> + *mmap_size = sizeof(*m) * 32;
> +again:
> + /*
> + * Add an additional 2 efi_memory_desc_t because we're doing an
> + * allocation which may be in a new descriptor region, and this
> + * may create additional entries.
> + */
> + *mmap_size += 2 * sizeof(*m);
> + status = sys_table_arg->BootServices->AllocatePool(EfiLoaderData,
> + *mmap_size, (void
> **)&m);
> + if ( status != EFI_SUCCESS )
> + goto fail;
> +
> + *desc_size = 0;
> + key = 0;
> + status = sys_table_arg->BootServices->GetMemoryMap(mmap_size, m,
> + &key, desc_size,
> &desc_version);
> + if ( status == EFI_BUFFER_TOO_SMALL )
> + {
> + sys_table_arg->BootServices->FreePool(m);
> + goto again;
> + }
> +
> + if ( status != EFI_SUCCESS )
> + sys_table_arg->BootServices->FreePool(m);
> +
> + if ( key_ptr && status == EFI_SUCCESS )
> + *key_ptr = key;
> + if ( desc_ver && status == EFI_SUCCESS )
> + *desc_ver = desc_version;
> +
> +fail:
> + *map = m;
I think if status != EFI_SUCCESS m is a free'd pointer? Probably best
not to tempt the caller with such a thing on failure.
> + return status;
> +}
> +
> +
> +static void __init *lookup_fdt_config_table(EFI_SYSTEM_TABLE *sys_table)
> +{
> + const EFI_GUID fdt_guid = DEVICE_TREE_GUID;
> + EFI_CONFIGURATION_TABLE *tables;
> + void *fdt;
> + int i;
> +
> + tables = sys_table->ConfigurationTable;
> + fdt = NULL;
> +
> + for ( i = 0; i < sys_table->NumberOfTableEntries; i++ ) if (
> match_guid(&tables[i].VendorGuid, &fdt_guid) == 0 )
I think this long line is the result of an accidentally omitted \n?
> + {
> + fdt = tables[i].VendorTable;
> + break;
> + }
> + return fdt;
> +}
> +
> +/*
> + * Get (or set if not present) the #addr-cells and #size cells
> + * properties of the chose node. We need to know these to properly
^chosen
> + * construct the address ranges used to describe the files loaded
> + * by the stub.
> + */
> +static int setup_chosen_node(void *fdt, int *addr_cells, int *size_cells)
These bits aren't __init?
> +
> +/*
> + * Set a single 'reg' property taking into account the
> + * configured addr and size cell sizes.
> + */
> +static int fdt_set_reg(void *fdt, int node, int addr_cells, int size_cells,
> + uint64_t addr, uint64_t len)
FWIW I think we have such a helper already somewhere, but perhaps this
file with -fshort-char etc is unable to call it?
> +{
> + uint8_t data[16]; /* at most 2 64 bit words */
> + void *p = data;
> +
> + /* Make sure that the values provided can be represented in
> + * the reg property.
> + */
> + if (addr_cells == 1 && (addr >> 32))
Xen coding style puts spaces more often than you may be used to. In
particular inside the brackets of an if (and while etc). So here:
if ( addr_cells == 1 && ( addr >> 32 ) )
> +
> +/*
> + * Add the FDT nodes for the standard EFI information, which consist
> + * of the System table address, the address of the final EFI memory map,
> + * and memory map information.
> + */
> +static EFI_STATUS fdt_add_uefi_nodes(EFI_SYSTEM_TABLE *sys_table, void *fdt,
> + EFI_MEMORY_DESCRIPTOR *memory_map,
> + unsigned long map_size, unsigned long
> desc_size,
> + u32 desc_ver)
> +{
> + int node;
> + int status;
> + u32 fdt_val32;
> + u64 fdt_val64;
> +
> +#ifndef ADD_EFI_MEMORY_TO_FDT
> + int prev;
> + /*
> + * Delete any memory nodes present. The EFI memory map is the only
> + * memory description provided to XEN.
> + */
> + prev = 0;
> + for (;;)
> + {
> + const char *type;
> + int len;
> +
> + node = fdt_next_node(fdt, prev, NULL);
> + if (node < 0)
> + break;
> +
> + type = fdt_getprop(fdt, node, "device_type", &len);
> + if (type && strncmp(type, "memory", len) == 0)
> + {
> + fdt_del_node(fdt, node);
> + continue;
> + }
> +
> + prev = node;
> + }
> +#endif
> +
> + node = fdt_subnode_offset(fdt, 0, "chosen");
> + if ( node < 0 )
> + {
> + node = fdt_add_subnode(fdt, 0, "chosen");
> + if ( node < 0 )
> + {
> + status = node; /* node is error code when negative */
> + goto fdt_set_fail;
> + }
> + }
> +
> + /* Add FDT entries for EFI runtime services in chosen node. */
> + node = fdt_subnode_offset(fdt, 0, "chosen");
You looked this up above (or created it), and with proper error
handling. I think you don't need to look again?
> [...]
> +}
Please can you include the emacs magic block you'll find in other files
at the end (and any other new files too)
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |