[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[xen staging] arm/efi: load dom0 modules from DT using UEFI



commit 048de2c47075d6106136bee110d4e930049a0fe3
Author:     Luca Fancellu <luca.fancellu@xxxxxxx>
AuthorDate: Mon Oct 11 19:15:28 2021 +0100
Commit:     Stefano Stabellini <stefano.stabellini@xxxxxxxxxx>
CommitDate: Wed Oct 13 11:09:46 2021 -0700

    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@xxxxxxx>
    Reviewed-by: Stefano Stabellini <sstabellini@xxxxxxxxxx>
    Acked-by: Jan Beulich <jbeulich@xxxxxxxx>
---
 docs/misc/arm/device-tree/booting.txt |  8 +++++
 docs/misc/efi.pandoc                  | 64 +++++++++++++++++++++++++++++++++--
 xen/arch/arm/efi/efi-boot.h           | 52 +++++++++++++++++++++++++---
 xen/common/efi/boot.c                 | 16 ++++++---
 4 files changed, 128 insertions(+), 12 deletions(-)

diff --git a/docs/misc/arm/device-tree/booting.txt 
b/docs/misc/arm/device-tree/booting.txt
index 7258e7e1ec..c6a775f4e8 100644
--- a/docs/misc/arm/device-tree/booting.txt
+++ b/docs/misc/arm/device-tree/booting.txt
@@ -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
 ========
 
diff --git a/docs/misc/efi.pandoc b/docs/misc/efi.pandoc
index 876cd55005..4abbb5bb82 100644
--- a/docs/misc/efi.pandoc
+++ b/docs/misc/efi.pandoc
@@ -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";
+               };
+       };
+};
+```
diff --git a/xen/arch/arm/efi/efi-boot.h b/xen/arch/arm/efi/efi-boot.h
index 0d86043567..8b88dd26a5 100644
--- a/xen/arch/arm/efi/efi-boot.h
+++ b/xen/arch/arm/efi/efi-boot.h
@@ -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 */
diff --git a/xen/common/efi/boot.c b/xen/common/efi/boot.c
index c9fdb5a3db..392ff3ac9b 100644
--- a/xen/common/efi/boot.c
+++ b/xen/common/efi/boot.c
@@ -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. */
--
generated by git-patchbot for /home/xen/git/xen.git#staging



 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.