[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 |