mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
arm/efi: load dom0 modules from DT using UEFI
Add support to load Dom0 boot modules from the device tree using the xen,uefi-binary property. Update documentation about that. Signed-off-by: Luca Fancellu <luca.fancellu@arm.com> Reviewed-by: Stefano Stabellini <sstabellini@kernel.org> Acked-by: Jan Beulich <jbeulich@suse.com>
This commit is contained in:
1 parent
9e319e5258
commit
048de2c470
4 files changed
+128
-12
No files matched your search
@@ -70,6 +70,14 @@ Each node contains the following properties:
|
||||
priority of this field vs. other mechanisms of specifying the
|
||||
bootargs for the 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 node needs to be
|
||||
compatible with multiboot,kernel or multiboot,ramdisk.
|
||||
|
||||
Examples
|
||||
========
|
||||
|
||||
|
||||
+61
-3
@@ -167,6 +167,28 @@ sbsign \
|
||||
--output xen.signed.efi \
|
||||
xen.unified.efi
|
||||
```
|
||||
## UEFI boot and Dom0 modules on ARM
|
||||
|
||||
When booting using UEFI on ARM, it is possible to specify the Dom0 modules
|
||||
directly from the device tree without using the Xen configuration file, here an
|
||||
example:
|
||||
|
||||
chosen {
|
||||
#size-cells = <0x1>;
|
||||
#address-cells = <0x1>;
|
||||
xen,xen-bootargs = "[Xen boot arguments]"
|
||||
|
||||
module@1 {
|
||||
compatible = "multiboot,kernel", "multiboot,module";
|
||||
xen,uefi-binary = "vmlinuz-3.0.31-0.4-xen";
|
||||
bootargs = "[domain 0 command line options]";
|
||||
};
|
||||
|
||||
module@2 {
|
||||
compatible = "multiboot,ramdisk", "multiboot,module";
|
||||
xen,uefi-binary = "initrd-3.0.31-0.4-xen";
|
||||
};
|
||||
}
|
||||
|
||||
## UEFI boot and dom0less on ARM
|
||||
|
||||
@@ -326,10 +348,10 @@ chosen {
|
||||
### 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.
|
||||
the configuration file can be processed or the Dom0 modules can be read from
|
||||
the device tree.
|
||||
|
||||
Here an example:
|
||||
Here the first example:
|
||||
|
||||
Xen configuration file:
|
||||
|
||||
@@ -369,4 +391,40 @@ chosen {
|
||||
};
|
||||
```
|
||||
|
||||
Here the second example:
|
||||
|
||||
Device tree:
|
||||
|
||||
```
|
||||
chosen {
|
||||
#size-cells = <0x1>;
|
||||
#address-cells = <0x1>;
|
||||
xen,xen-bootargs = "[Xen boot arguments]"
|
||||
|
||||
module@1 {
|
||||
compatible = "multiboot,kernel", "multiboot,module";
|
||||
xen,uefi-binary = "vmlinuz-3.0.31-0.4-xen";
|
||||
bootargs = "[domain 0 command line options]";
|
||||
};
|
||||
|
||||
module@2 {
|
||||
compatible = "multiboot,ramdisk", "multiboot,module";
|
||||
xen,uefi-binary = "initrd-3.0.31-0.4-xen";
|
||||
};
|
||||
|
||||
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";
|
||||
};
|
||||
};
|
||||
};
|
||||
```
|
||||
@@ -32,8 +32,12 @@ static unsigned int __initdata modules_idx;
|
||||
#define ERROR_RENAME_MODULE_NAME (-4)
|
||||
#define ERROR_SET_REG_PROPERTY (-5)
|
||||
#define ERROR_CHECK_MODULE_COMPAT (-6)
|
||||
#define ERROR_DOM0_ALREADY_FOUND (-7)
|
||||
#define ERROR_DOM0_RAMDISK_FOUND (-8)
|
||||
#define ERROR_XSM_ALREADY_FOUND (-9)
|
||||
#define ERROR_DT_MODULE_DOMU (-1)
|
||||
#define ERROR_DT_CHOSEN_NODE (-2)
|
||||
#define ERROR_DT_MODULE_DOM0 (-3)
|
||||
|
||||
void noreturn efi_xen_start(void *fdt_ptr, uint32_t fdt_size);
|
||||
void __flush_dcache_area(const void *vaddr, unsigned long size);
|
||||
@@ -46,7 +50,8 @@ static int allocate_module_file(EFI_FILE_HANDLE dir_handle,
|
||||
static int handle_module_node(EFI_FILE_HANDLE dir_handle,
|
||||
int module_node_offset,
|
||||
int reg_addr_cells,
|
||||
int reg_size_cells);
|
||||
int reg_size_cells,
|
||||
bool is_domu_module);
|
||||
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);
|
||||
@@ -701,7 +706,8 @@ static int __init allocate_module_file(EFI_FILE_HANDLE dir_handle,
|
||||
static int __init handle_module_node(EFI_FILE_HANDLE dir_handle,
|
||||
int module_node_offset,
|
||||
int reg_addr_cells,
|
||||
int reg_size_cells)
|
||||
int reg_size_cells,
|
||||
bool is_domu_module)
|
||||
{
|
||||
const void *uefi_name_prop;
|
||||
char mod_string[24]; /* Placeholder for module@ + a 64-bit number + \0 */
|
||||
@@ -754,6 +760,41 @@ static int __init handle_module_node(EFI_FILE_HANDLE dir_handle,
|
||||
return ERROR_SET_REG_PROPERTY;
|
||||
}
|
||||
|
||||
if ( !is_domu_module )
|
||||
{
|
||||
if ( (fdt_node_check_compatible(fdt, module_node_offset,
|
||||
"multiboot,kernel") == 0) )
|
||||
{
|
||||
/*
|
||||
* This is the Dom0 kernel, wire it to the kernel variable because it
|
||||
* will be verified by the shim lock protocol later in the common
|
||||
* code.
|
||||
*/
|
||||
if ( kernel.addr )
|
||||
{
|
||||
PrintMessage(L"Dom0 kernel already found in cfg file.");
|
||||
return ERROR_DOM0_ALREADY_FOUND;
|
||||
}
|
||||
kernel.need_to_free = false; /* Freed using the module array */
|
||||
kernel.addr = file->addr;
|
||||
kernel.size = file->size;
|
||||
}
|
||||
else if ( ramdisk.addr &&
|
||||
(fdt_node_check_compatible(fdt, module_node_offset,
|
||||
"multiboot,ramdisk") == 0) )
|
||||
{
|
||||
PrintMessage(L"Dom0 ramdisk already found in cfg file.");
|
||||
return ERROR_DOM0_RAMDISK_FOUND;
|
||||
}
|
||||
else if ( xsm.addr &&
|
||||
(fdt_node_check_compatible(fdt, module_node_offset,
|
||||
"xen,xsm-policy") == 0) )
|
||||
{
|
||||
PrintMessage(L"XSM policy already found in cfg file.");
|
||||
return ERROR_XSM_ALREADY_FOUND;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -793,7 +834,7 @@ static int __init handle_dom0less_domain_node(EFI_FILE_HANDLE dir_handle,
|
||||
module_node = fdt_next_subnode(fdt, module_node) )
|
||||
{
|
||||
int ret = handle_module_node(dir_handle, module_node, addr_cells,
|
||||
size_cells);
|
||||
size_cells, true);
|
||||
if ( ret < 0 )
|
||||
return ret;
|
||||
}
|
||||
@@ -803,7 +844,7 @@ static int __init handle_dom0less_domain_node(EFI_FILE_HANDLE dir_handle,
|
||||
|
||||
/*
|
||||
* This function checks for xen domain nodes under the /chosen node for possible
|
||||
* domU guests to be loaded.
|
||||
* dom0 and 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)
|
||||
@@ -830,6 +871,9 @@ static int __init efi_check_dt_boot(EFI_FILE_HANDLE dir_handle)
|
||||
if ( handle_dom0less_domain_node(dir_handle, node) < 0 )
|
||||
return ERROR_DT_MODULE_DOMU;
|
||||
}
|
||||
else if ( handle_module_node(dir_handle, node, addr_len, size_len,
|
||||
false) < 0 )
|
||||
return ERROR_DT_MODULE_DOM0;
|
||||
}
|
||||
|
||||
/* Free boot modules file names if any */
|
||||
|
||||
+11
-5
@@ -1302,11 +1302,6 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
|
||||
{
|
||||
read_file(dir_handle, s2w(&name), &kernel, option_str);
|
||||
efi_bs->FreePool(name.w);
|
||||
|
||||
if ( !EFI_ERROR(efi_bs->LocateProtocol(&shim_lock_guid, NULL,
|
||||
(void **)&shim_lock)) &&
|
||||
(status = shim_lock->Verify(kernel.ptr, kernel.size)) != EFI_SUCCESS )
|
||||
PrintErrMesg(L"Dom0 kernel image could not be verified", status);
|
||||
}
|
||||
|
||||
if ( !read_section(loaded_image, L"ramdisk", &ramdisk, NULL) )
|
||||
@@ -1384,6 +1379,17 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
|
||||
if ( !dt_modules_found && !kernel.ptr )
|
||||
blexit(L"No initial domain kernel specified.");
|
||||
|
||||
/*
|
||||
* The Dom0 kernel can be loaded from the configuration file or by the
|
||||
* device tree through the efi_check_dt_boot function, in this stage
|
||||
* verify it.
|
||||
*/
|
||||
if ( kernel.ptr &&
|
||||
!EFI_ERROR(efi_bs->LocateProtocol(&shim_lock_guid, NULL,
|
||||
(void **)&shim_lock)) &&
|
||||
(status = shim_lock->Verify(kernel.ptr, kernel.size)) != EFI_SUCCESS )
|
||||
PrintErrMesg(L"Dom0 kernel image could not be verified", status);
|
||||
|
||||
efi_arch_edd();
|
||||
|
||||
/* XXX Collect EDID info. */
|
||||
|
||||