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:
Luca Fancellu authored and Stefano Stabellini committed 2021-10-13 11:09:46 -07:00
1 parent 9e319e5258
commit 048de2c470
4 files changed
+128 -12

No files matched your search

+8
View File
@@ -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
View File
@@ -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";
};
};
};
```
+48 -4
View File
@@ -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
View File
@@ -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. */
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.