[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH v6 1/2] arm/efi: Use dom0less configuration when using EFI boot
On Mon, 11 Oct 2021, Luca Fancellu wrote: > This patch introduces the support for dom0less configuration > when using UEFI boot on ARM, it permits the EFI boot to > continue if no dom0 kernel is specified but at least one domU > is found. > > Introduce the new property "xen,uefi-binary" for device tree boot > module nodes that are subnode of "xen,domain" compatible nodes. > The property holds a string containing the file name of the > binary that shall be loaded by the uefi loader from the filesystem. > > Introduce a new call efi_check_dt_boot(...) called during EFI boot > that checks for module to be loaded using device tree. > Architectures that don't support device tree don't have to > provide this function. > > Update efi documentation about how to start a dom0less > setup using UEFI > > Signed-off-by: Luca Fancellu <luca.fancellu@xxxxxxx> Reviewed-by: Stefano Stabellini <sstabellini@xxxxxxxxxx> > --- > Changes in v6: > - change is_boot_module() to check for every multiboot,module > instead of multiboot,{kernel,ramdisk,device-tree} (Julien), as > a result of that remove the function and put the check inside of > handle_module_node(...) > Changes in v5: > - Removed unneeded variable initialization > - Fixed comment > - Fixed error message for the absence of an initial domain kernel > - changed efi_arch_check_dt_boot to efi_check_dt_boot and add > a stub if CONFIG_HAS_DEVICE_TREE is not declared, updated commit > message about the call introduction in the EFI boot flow. > Changes in v4: > - update uefi,cfg-load to xen,uefi-cfg-load in documentation > - fixed comments and code style > - changed variable name from dt_module_found to dt_modules_found > in boot.c > - removed stub efi_arch_check_dt_boot from x86 code because the > architecture does not support DT, protected call with #ifdef > in the common code. > - add comment to explain the result from efi_arch_check_dt_boot > just looking the common code > - Add space before comment in boot.c > - renamed uefi,binary property to xen,uefi-binary > Changes in v3: > - fixed documentation > - fixed name len in strlcpy > - fixed some style issues > - closed filesystem handle before calling blexit > - passed runtime errors up to the stack instead > of calling blexit > - renamed names and function to make them more > general in prevision to load also Dom0 kernel > and ramdisk from DT > Changes in v2: > - remove array of struct file > - fixed some int types > - Made the code use filesystem even when configuration > file is skipped. > - add documentation of uefi,binary in booting.txt > - add documentation on how to boot all configuration > for Xen using UEFI in efi.pandoc > --- > docs/misc/arm/device-tree/booting.txt | 21 ++ > docs/misc/efi.pandoc | 203 +++++++++++++++++ > xen/arch/arm/efi/efi-boot.h | 299 +++++++++++++++++++++++++- > xen/common/efi/boot.c | 39 +++- > 4 files changed, 550 insertions(+), 12 deletions(-) > > diff --git a/docs/misc/arm/device-tree/booting.txt > b/docs/misc/arm/device-tree/booting.txt > index 352b0ec43a..7258e7e1ec 100644 > --- a/docs/misc/arm/device-tree/booting.txt > +++ b/docs/misc/arm/device-tree/booting.txt > @@ -190,6 +190,13 @@ The kernel sub-node has the following properties: > > Command line parameters for the guest kernel. > > +- xen,uefi-binary (UEFI boot only) > + > + String property that specifies the file name to be loaded by the UEFI > boot > + for this module. If this is specified, there is no need to specify the > reg > + property because it will be created by the UEFI stub on boot. > + This option is needed only when UEFI boot is used. > + > The ramdisk sub-node has the following properties: > > - compatible > @@ -201,6 +208,13 @@ The ramdisk sub-node has the following properties: > Specifies the physical address of the ramdisk in RAM and its > length. > > +- xen,uefi-binary (UEFI boot only) > + > + String property that specifies the file name to be loaded by the UEFI > boot > + for this module. If this is specified, there is no need to specify the > reg > + property because it will be created by the UEFI stub on boot. > + This option is needed only when UEFI boot is used. > + > > Example > ======= > @@ -265,6 +279,13 @@ The dtb sub-node should have the following properties: > Specifies the physical address of the device tree binary fragment > RAM and its length. > > +- xen,uefi-binary (UEFI boot only) > + > + String property that specifies the file name to be loaded by the UEFI > boot > + for this module. If this is specified, there is no need to specify the > reg > + property because it will be created by the UEFI stub on boot. > + This option is needed only when UEFI boot is used. > + > As an example: > > module@0xc000000 { > diff --git a/docs/misc/efi.pandoc b/docs/misc/efi.pandoc > index ed85351541..876cd55005 100644 > --- a/docs/misc/efi.pandoc > +++ b/docs/misc/efi.pandoc > @@ -167,3 +167,206 @@ sbsign \ > --output xen.signed.efi \ > xen.unified.efi > ``` > + > +## UEFI boot and dom0less on ARM > + > +Dom0less feature is supported by ARM and it is possible to use it when Xen is > +started as an EFI application. > +The way to specify the domU domains is by Device Tree as specified in the > +[dom0less](dom0less.html) documentation page under the "Device Tree > +configuration" section, but instead of declaring the reg property in the boot > +module, the user must specify the "xen,uefi-binary" property containing the > name > +of the binary file that has to be loaded in memory. > +The UEFI stub will load the binary in memory and it will add the reg property > +accordingly. > + > +An example here: > + > +domU1 { > + #address-cells = <1>; > + #size-cells = <1>; > + compatible = "xen,domain"; > + memory = <0 0x20000>; > + cpus = <1>; > + vpl011; > + > + module@1 { > + compatible = "multiboot,kernel", "multiboot,module"; > + xen,uefi-binary = "vmlinuz-3.0.31-0.4-xen"; > + bootargs = "console=ttyAMA0"; > + }; > + module@2 { > + compatible = "multiboot,ramdisk", "multiboot,module"; > + xen,uefi-binary = "initrd-3.0.31-0.4-xen"; > + }; > + module@3 { > + compatible = "multiboot,ramdisk", "multiboot,module"; > + xen,uefi-binary = "passthrough.dtb"; > + }; > +}; > + > +## How to boot different Xen setup using UEFI > + > +These are the different ways to boot a Xen system from UEFI: > + > + - Boot Xen and Dom0 (minimum required) > + - Boot Xen and DomU(s) (true dom0less, only on ARM) > + - Boot Xen, Dom0 and DomU(s) (only on ARM) > + > +### Boot Xen and Dom0 > + > +This configuration can be started using the Xen configuration file in the > +example above. > + > +### Boot Xen and DomU(s) > + > +This configuration needs the domU domain(s) specified in the /chosen node, > +examples of how to do that are provided by the documentation about dom0less > +and the example above shows how to use the "xen,uefi-binary" property to use > the > +UEFI stub for module loading. > +When adding DomU modules to device tree, also add the property > +xen,uefi-cfg-load under chosen for Xen to load the Xen config file. > +Otherwise, Xen will skip the config file and rely on device tree alone. > + > +Example 1 of how to boot a true dom0less configuration: > + > +Xen configuration file: skipped. > + > +Device tree: > + > +``` > +chosen { > + #size-cells = <0x1>; > + #address-cells = <0x1>; > + xen,xen-bootargs = "<Xen command line>" > + > + domU1 { > + #size-cells = <0x1>; > + #address-cells = <0x1>; > + compatible = "xen,domain"; > + cpus = <0x1>; > + memory = <0x0 0xc0000>; > + vpl011; > + > + module@1 { > + compatible = "multiboot,kernel", "multiboot,module"; > + xen,uefi-binary = "Image-domu1.bin"; > + bootargs = "console=ttyAMA0 root=/dev/ram0 rw"; > + }; > + }; > + domU2 { > + #size-cells = <0x1>; > + #address-cells = <0x1>; > + compatible = "xen,domain"; > + cpus = <0x1>; > + memory = <0x0 0x100000>; > + vpl011; > + > + module@2 { > + compatible = "multiboot,kernel", "multiboot,module"; > + xen,uefi-binary = "Image-domu2.bin"; > + bootargs = "console=ttyAMA0 root=/dev/ram0 rw"; > + }; > + }; > +}; > +``` > + > +Example 2 of how to boot a true dom0less configuration: > + > +Xen configuration file: > + > +``` > +[global] > +default=xen > + > +[xen] > +options=<Xen command line> > +dtb=<optional DTB> > +``` > + > +Device tree: > + > +``` > +chosen { > + #size-cells = <0x1>; > + #address-cells = <0x1>; > + xen,uefi-cfg-load; > + > + domU1 { > + #size-cells = <0x1>; > + #address-cells = <0x1>; > + compatible = "xen,domain"; > + cpus = <0x1>; > + memory = <0x0 0xc0000>; > + vpl011; > + > + module@1 { > + compatible = "multiboot,kernel", "multiboot,module"; > + xen,uefi-binary = "Image-domu1.bin"; > + bootargs = "console=ttyAMA0 root=/dev/ram0 rw"; > + }; > + }; > + domU2 { > + #size-cells = <0x1>; > + #address-cells = <0x1>; > + compatible = "xen,domain"; > + cpus = <0x1>; > + memory = <0x0 0x100000>; > + vpl011; > + > + module@2 { > + compatible = "multiboot,kernel", "multiboot,module"; > + xen,uefi-binary = "Image-domu2.bin"; > + bootargs = "console=ttyAMA0 root=/dev/ram0 rw"; > + }; > + }; > +}; > +``` > + > +### Boot Xen, Dom0 and DomU(s) > + > +This configuration is a mix of the two configuration above, to boot this one > +the configuration file must be processed so the /chosen node must have the > +"xen,uefi-cfg-load" property. > + > +Here an example: > + > +Xen configuration file: > + > +``` > +[global] > +default=xen > + > +[xen] > +options=<Xen command line> > +kernel=vmlinuz-3.0.31-0.4-xen [domain 0 command line options] > +ramdisk=initrd-3.0.31-0.4-xen > +dtb=<optional DTB> > +``` > + > +Device tree: > + > +``` > +chosen { > + #size-cells = <0x1>; > + #address-cells = <0x1>; > + xen,uefi-cfg-load; > + > + domU1 { > + #size-cells = <0x1>; > + #address-cells = <0x1>; > + compatible = "xen,domain"; > + cpus = <0x1>; > + memory = <0x0 0xc0000>; > + vpl011; > + > + module@1 { > + compatible = "multiboot,kernel", "multiboot,module"; > + xen,uefi-binary = "Image-domu1.bin"; > + bootargs = "console=ttyAMA0 root=/dev/ram0 rw"; > + }; > + }; > +}; > +``` > + > + > diff --git a/xen/arch/arm/efi/efi-boot.h b/xen/arch/arm/efi/efi-boot.h > index a3e46453d4..f35e035b22 100644 > --- a/xen/arch/arm/efi/efi-boot.h > +++ b/xen/arch/arm/efi/efi-boot.h > @@ -8,9 +8,49 @@ > #include <asm/setup.h> > #include <asm/smp.h> > > +typedef struct { > + char *name; > + unsigned int name_len; > + EFI_PHYSICAL_ADDRESS addr; > + UINTN size; > +} module_name; > + > +/* > + * Binaries will be translated into bootmodules, the maximum number for them > is > + * MAX_MODULES where we should remove a unit for Xen and one for Xen DTB > + */ > +#define MAX_UEFI_MODULES (MAX_MODULES - 2) > +static struct file __initdata module_binary; > +static module_name __initdata modules[MAX_UEFI_MODULES]; > +static unsigned int __initdata modules_available = MAX_UEFI_MODULES; > +static unsigned int __initdata modules_idx; > + > +#define ERROR_BINARY_FILE_NOT_FOUND (-1) > +#define ERROR_ALLOC_MODULE_NO_SPACE (-1) > +#define ERROR_ALLOC_MODULE_NAME (-2) > +#define ERROR_MISSING_DT_PROPERTY (-3) > +#define ERROR_RENAME_MODULE_NAME (-4) > +#define ERROR_SET_REG_PROPERTY (-5) > +#define ERROR_CHECK_MODULE_COMPAT (-6) > +#define ERROR_DT_MODULE_DOMU (-1) > +#define ERROR_DT_CHOSEN_NODE (-2) > + > void noreturn efi_xen_start(void *fdt_ptr, uint32_t fdt_size); > void __flush_dcache_area(const void *vaddr, unsigned long size); > > +static int get_module_file_index(const char *name, unsigned int name_len); > +static void PrintMessage(const CHAR16 *s); > +static int allocate_module_file(EFI_FILE_HANDLE dir_handle, > + const char *name, > + unsigned int name_len); > +static int handle_module_node(EFI_FILE_HANDLE dir_handle, > + int module_node_offset, > + int reg_addr_cells, > + int reg_size_cells); > +static int handle_dom0less_domain_node(EFI_FILE_HANDLE dir_handle, > + int domain_node); > +static int efi_check_dt_boot(EFI_FILE_HANDLE dir_handle); > + > #define DEVICE_TREE_GUID \ > {0xb1b621d5, 0xf19c, 0x41a5, {0x83, 0x0b, 0xd9, 0x15, 0x2c, 0x69, 0xaa, > 0xe0}} > > @@ -552,8 +592,254 @@ static void __init efi_arch_handle_module(const struct > file *file, > kernel.size) < 0 ) > blexit(L"Unable to set reg property."); > } > - else > + else if ( file != &module_binary ) > + /* > + * If file is not a dom0 module file and it's not a domU module, > + * stop here. > + */ > blexit(L"Unknown module type"); > + > + /* > + * modules_available is decremented here because for each dom0 file added > + * from the configuration file, there will be an additional bootmodule, > + * so the number of available slots will be decremented because there is > a > + * maximum amount of bootmodules that can be loaded. > + */ > + modules_available--; > +} > + > +/* > + * This function checks for a binary previously loaded with a give name, it > + * returns the index of the file in the modules array or a negative number > if no > + * file with that name is found. > + */ > +static int __init get_module_file_index(const char *name, > + unsigned int name_len) > +{ > + unsigned int i; > + int ret = ERROR_BINARY_FILE_NOT_FOUND; > + > + for ( i = 0; i < modules_idx; i++ ) > + { > + module_name *mod = &modules[i]; > + if ( (mod->name_len == name_len) && > + (strncmp(mod->name, name, name_len) == 0) ) > + { > + ret = i; > + break; > + } > + } > + return ret; > +} > + > +static void __init PrintMessage(const CHAR16 *s) > +{ > + PrintStr(s); > + PrintStr(newline); > +} > + > +/* > + * This function allocates a binary and keeps track of its name, it returns > the > + * index of the file in the modules array or a negative number on error. > + */ > +static int __init allocate_module_file(EFI_FILE_HANDLE dir_handle, > + const char *name, > + unsigned int name_len) > +{ > + module_name *file_name; > + union string module_name; > + int ret; > + > + /* > + * Check if there is any space left for a module, the variable > + * modules_available is updated each time we use read_file(...) > + * successfully. > + */ > + if ( !modules_available ) > + { > + PrintMessage(L"No space left for modules"); > + return ERROR_ALLOC_MODULE_NO_SPACE; > + } > + > + module_name.cs = name; > + ret = modules_idx; > + > + /* Save at this index the name of this binary */ > + file_name = &modules[ret]; > + > + if ( efi_bs->AllocatePool(EfiLoaderData, (name_len + 1) * sizeof(char), > + (void**)&file_name->name) != EFI_SUCCESS ) > + { > + PrintMessage(L"Error allocating memory for module binary name"); > + return ERROR_ALLOC_MODULE_NAME; > + } > + > + /* Save name and length of the binary in the data structure */ > + strlcpy(file_name->name, name, name_len + 1); > + file_name->name_len = name_len; > + > + /* Load the binary in memory */ > + read_file(dir_handle, s2w(&module_name), &module_binary, NULL); > + > + /* Save address and size */ > + file_name->addr = module_binary.addr; > + file_name->size = module_binary.size; > + > + /* s2w(...) allocates some memory, free it */ > + efi_bs->FreePool(module_name.w); > + > + modules_idx++; > + > + return ret; > +} > + > +/* > + * This function checks for the presence of the xen,uefi-binary property in > the > + * module, if found it loads the binary as module and sets the right address > + * for the reg property into the module DT node. > + */ > +static int __init handle_module_node(EFI_FILE_HANDLE dir_handle, > + int module_node_offset, > + int reg_addr_cells, > + int reg_size_cells) > +{ > + const void *uefi_name_prop; > + char mod_string[24]; /* Placeholder for module@ + a 64-bit number + \0 */ > + int uefi_name_len, file_idx, module_compat; > + module_name *file; > + > + /* Check if the node is a multiboot,module otherwise return */ > + module_compat = fdt_node_check_compatible(fdt, module_node_offset, > + "multiboot,module"); > + if ( module_compat < 0 ) > + /* Error while checking the compatible string */ > + return ERROR_CHECK_MODULE_COMPAT; > + > + if ( module_compat != 0 ) > + /* Module is not a multiboot,module */ > + return 0; > + > + /* Read xen,uefi-binary property to get the file name. */ > + uefi_name_prop = fdt_getprop(fdt, module_node_offset, "xen,uefi-binary", > + &uefi_name_len); > + > + if ( !uefi_name_prop ) > + /* Property not found */ > + return 0; > + > + file_idx = get_module_file_index(uefi_name_prop, uefi_name_len); > + if ( file_idx < 0 ) > + { > + file_idx = allocate_module_file(dir_handle, uefi_name_prop, > + uefi_name_len); > + if ( file_idx < 0 ) > + return file_idx; > + } > + > + file = &modules[file_idx]; > + > + snprintf(mod_string, sizeof(mod_string), "module@%"PRIx64, file->addr); > + > + /* Rename the module to be module@{address} */ > + if ( fdt_set_name(fdt, module_node_offset, mod_string) < 0 ) > + { > + PrintMessage(L"Unable to modify module node name."); > + return ERROR_RENAME_MODULE_NAME; > + } > + > + if ( fdt_set_reg(fdt, module_node_offset, reg_addr_cells, reg_size_cells, > + file->addr, file->size) < 0 ) > + { > + PrintMessage(L"Unable to set module reg property."); > + return ERROR_SET_REG_PROPERTY; > + } > + > + return 0; > +} > + > +/* > + * This function checks for boot modules under the domU guest domain node > + * in the DT. > + * Returns 0 on success, negative number on error. > + */ > +static int __init handle_dom0less_domain_node(EFI_FILE_HANDLE dir_handle, > + int domain_node) > +{ > + int module_node, addr_cells, size_cells, len; > + const struct fdt_property *prop; > + > + /* Get #address-cells and #size-cells from domain node */ > + prop = fdt_get_property(fdt, domain_node, "#address-cells", &len); > + if ( !prop ) > + { > + PrintMessage(L"#address-cells not found in domain node."); > + return ERROR_MISSING_DT_PROPERTY; > + } > + > + addr_cells = fdt32_to_cpu(*((uint32_t *)prop->data)); > + > + prop = fdt_get_property(fdt, domain_node, "#size-cells", &len); > + if ( !prop ) > + { > + PrintMessage(L"#size-cells not found in domain node."); > + return ERROR_MISSING_DT_PROPERTY; > + } > + > + size_cells = fdt32_to_cpu(*((uint32_t *)prop->data)); > + > + /* Check for nodes compatible with multiboot,module inside this node */ > + for ( module_node = fdt_first_subnode(fdt, domain_node); > + module_node > 0; > + module_node = fdt_next_subnode(fdt, module_node) ) > + { > + int ret = handle_module_node(dir_handle, module_node, addr_cells, > + size_cells); > + if ( ret < 0 ) > + return ret; > + } > + > + return 0; > +} > + > +/* > + * This function checks for xen domain nodes under the /chosen node for > possible > + * domU guests to be loaded. > + * Returns the number of modules loaded or a negative number for error. > + */ > +static int __init efi_check_dt_boot(EFI_FILE_HANDLE dir_handle) > +{ > + int chosen, node, addr_len, size_len; > + unsigned int i = 0; > + > + /* Check for the chosen node in the current DTB */ > + chosen = setup_chosen_node(fdt, &addr_len, &size_len); > + if ( chosen < 0 ) > + { > + PrintMessage(L"Unable to setup chosen node"); > + return ERROR_DT_CHOSEN_NODE; > + } > + > + /* Check for nodes compatible with xen,domain under the chosen node */ > + for ( node = fdt_first_subnode(fdt, chosen); > + node > 0; > + node = fdt_next_subnode(fdt, node) ) > + { > + if ( !fdt_node_check_compatible(fdt, node, "xen,domain") ) > + { > + /* Found a node with compatible xen,domain; handle this node. */ > + if ( handle_dom0less_domain_node(dir_handle, node) < 0 ) > + return ERROR_DT_MODULE_DOMU; > + } > + } > + > + /* Free boot modules file names if any */ > + for ( ; i < modules_idx; i++ ) > + { > + /* Free boot modules binary names */ > + efi_bs->FreePool(modules[i].name); > + } > + > + return modules_idx; > } > > static void __init efi_arch_cpu(void) > @@ -562,8 +848,19 @@ static void __init efi_arch_cpu(void) > > static void __init efi_arch_blexit(void) > { > + unsigned int i = 0; > + > if ( dtbfile.need_to_free ) > efi_bs->FreePages(dtbfile.addr, PFN_UP(dtbfile.size)); > + /* Free boot modules file names if any */ > + for ( ; i < modules_idx; i++ ) > + { > + /* Free boot modules binary names */ > + efi_bs->FreePool(modules[i].name); > + /* Free modules binaries */ > + efi_bs->FreePages(modules[i].addr, > + PFN_UP(modules[i].size)); > + } > if ( memmap ) > efi_bs->FreePool(memmap); > } > diff --git a/xen/common/efi/boot.c b/xen/common/efi/boot.c > index 758f9d74d2..7879b93f93 100644 > --- a/xen/common/efi/boot.c > +++ b/xen/common/efi/boot.c > @@ -166,6 +166,13 @@ static void __init PrintErr(const CHAR16 *s) > StdErr->OutputString(StdErr, (CHAR16 *)s ); > } > > +#ifndef CONFIG_HAS_DEVICE_TREE > +static inline int __init efi_check_dt_boot(EFI_FILE_HANDLE dir_handle) > +{ > + return 0; > +} > +#endif > + > /* > * Include architecture specific implementation here, which references the > * static globals defined above. > @@ -1136,6 +1143,8 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE > *SystemTable) > bool base_video = false; > const char *option_str; > bool use_cfg_file; > + int dt_modules_found; > + EFI_FILE_HANDLE dir_handle; > > __set_bit(EFI_BOOT, &efi_flags); > __set_bit(EFI_LOADER, &efi_flags); > @@ -1216,9 +1225,11 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE > *SystemTable) > > efi_arch_relocate_image(0); > > + /* Get the file system interface. */ > + dir_handle = get_parent_handle(loaded_image, &file_name); > + > if ( use_cfg_file ) > { > - EFI_FILE_HANDLE dir_handle; > UINTN depth, cols, rows, size; > > size = cols = rows = depth = 0; > @@ -1229,9 +1240,6 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE > *SystemTable) > > gop = efi_get_gop(); > > - /* Get the file system interface. */ > - dir_handle = get_parent_handle(loaded_image, &file_name); > - > /* Read and parse the config file. */ > if ( read_section(loaded_image, L"config", &cfg, NULL) ) > PrintStr(L"Using builtin config file\r\n"); > @@ -1285,14 +1293,12 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE > *SystemTable) > efi_bs->FreePool(name.w); > } > > - if ( !name.s ) > - blexit(L"No Dom0 kernel image specified."); > - > efi_arch_cfg_file_early(loaded_image, dir_handle, section.s); > > - option_str = split_string(name.s); > + option_str = name.s ? split_string(name.s) : NULL; > > - if ( !read_section(loaded_image, L"kernel", &kernel, option_str) ) > + if ( !read_section(loaded_image, L"kernel", &kernel, option_str) && > + name.s ) > { > read_file(dir_handle, s2w(&name), &kernel, option_str); > efi_bs->FreePool(name.w); > @@ -1361,12 +1367,23 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE > *SystemTable) > efi_bs->FreePages(cfg.addr, PFN_UP(cfg.size)); > cfg.addr = 0; > > - dir_handle->Close(dir_handle); > - > if ( gop && !base_video ) > gop_mode = efi_find_gop_mode(gop, cols, rows, depth); > } > > + /* Get the number of boot modules specified on the DT or an error (<0) */ > + dt_modules_found = efi_check_dt_boot(dir_handle); > + > + dir_handle->Close(dir_handle); > + > + if ( dt_modules_found < 0 ) > + /* efi_check_dt_boot throws some error */ > + blexit(L"Error processing boot modules on DT."); > + > + /* Check if at least one of Dom0 or DomU(s) is specified */ > + if ( !dt_modules_found && !kernel.ptr ) > + blexit(L"No initial domain kernel specified."); > + > efi_arch_edd(); > > /* XXX Collect EDID info. */ > -- > 2.17.1 >
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |