summaryrefslogtreecommitdiffstats
path: root/xen/xen-efi-tboot-launch.patch
blob: 9fb99c191483e1d9a9799c16310ce438020c653e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
Index: xen-4.7.1/xen/arch/x86/efi/efi-tboot.h
===================================================================
--- /dev/null
+++ xen-4.7.1/xen/arch/x86/efi/efi-tboot.h
@@ -0,0 +1,35 @@
+#ifndef __EFITBOOT_H__
+#define __EFITBOOT_H__
+
+/* Shared RT variable between TBOOT and Xen */
+#define EFI_TBOOT_XEN_GUID \
+    { 0xf112e6cb, 0xce01, 0x4573, {0xa0, 0x52, 0xfb, 0xdb, 0x6c, 0xc0, 0xc7, 0xcb} }
+
+#define EFI_TBOOT_XEN_REV  1
+#define EFI_TBOOT_XEN_NAME L"TbootXenVar"
+
+static EFI_GUID __initdata TbootXenGuid = EFI_TBOOT_XEN_GUID;
+
+typedef void (*post_launch_t)(void *ets);
+
+typedef struct __packed efi_xen_tboot_data {
+    void *kernel;
+    uint64_t kernel_size;
+    void *ramdisk;
+    uint64_t ramdisk_size;
+    void *memory_map;
+    uint64_t memory_map_size;
+    uint64_t memory_desc_size;
+    uint64_t post_launch_cb;
+} efi_xen_tboot_data_t;
+
+typedef void (*begin_launch_t)(struct efi_xen_tboot_data *xtd);
+
+typedef struct __packed efi_tboot_xen_var {
+    uint64_t revision;
+    const char *xen_config;
+    uint64_t xen_config_size;
+    uint64_t begin_launch_cb;
+} efi_tboot_xen_var_t;
+
+#endif /* __EFITBOOT_H__ */
Index: xen-4.7.1/xen/common/efi/boot.c
===================================================================
--- xen-4.7.1.orig/xen/common/efi/boot.c
+++ xen-4.7.1/xen/common/efi/boot.c
@@ -79,6 +79,7 @@ static size_t wstrlen(const CHAR16 * s);
 static int set_color(u32 mask, int bpp, u8 *pos, u8 *sz);
 static bool_t match_guid(const EFI_GUID *guid1, const EFI_GUID *guid2);
 
+static const EFI_SYSTEM_TABLE *__initdata efi_st;
 static const EFI_BOOT_SERVICES *__initdata efi_bs;
 static UINT32 __initdata efi_bs_revision;
 static EFI_HANDLE __initdata efi_ih;
@@ -98,6 +99,14 @@ static CHAR16 __initdata newline[] = L"\
 #define PrintStr(s) StdOut->OutputString(StdOut, s)
 #define PrintErr(s) StdErr->OutputString(StdErr, s)
 
+/* TBOOT specific definitions */
+#include "efi-tboot.h"
+
+static struct efi_tboot_xen_var __initdata txv;
+static struct efi_xen_tboot_data __initdata xtd;
+static void* __initdata xtd_memmap;
+extern void *g_efi_tboot_shared;
+
 /*
  * Include architecture specific implementation here, which references the
  * static globals defined above.
@@ -580,6 +589,7 @@ static char *__init get_value(const stru
 static void __init efi_init(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
 {
     efi_ih = ImageHandle;
+    efi_st = SystemTable;
     efi_bs = SystemTable->BootServices;
     efi_bs_revision = efi_bs->Hdr.Revision;
     efi_rs = SystemTable->RuntimeServices;
@@ -839,6 +849,95 @@ static void __init efi_variables(void)
     }
 }
 
+#if 0
+static void __init efi_debug_pause(void)
+{
+    EFI_STATUS    status;
+    EFI_INPUT_KEY key;
+
+    PrintStr(L"Pause...");
+    efi_st->ConIn->Reset(efi_st->ConIn, FALSE);
+    while ((status = efi_st->ConIn->ReadKeyStroke(efi_st->ConIn, &key)) == EFI_NOT_READY);
+}
+#endif
+
+static void __init efi_xen_tboot_variable(void)
+{
+    EFI_STATUS status;
+    UINTN size = 0;
+
+    status = efi_rs->GetVariable(EFI_TBOOT_XEN_NAME,
+                                 &TbootXenGuid,
+                                 NULL,
+                                 &size,
+                                 NULL);
+
+    /* No TBOOT/Xen variable */
+    if ( EFI_ERROR(status) && status != EFI_BUFFER_TOO_SMALL )
+        return;
+
+    if (size != sizeof(struct efi_tboot_xen_var)) {
+        PrintStr(L"Warning: TBOOT/Xen shared variable, wrong size: ");
+        DisplayUint(size, 0);
+        PrintStr(newline);
+        return;
+    }
+
+    status = efi_rs->GetVariable(EFI_TBOOT_XEN_NAME,
+                                 &TbootXenGuid,
+                                 NULL,
+                                 &size,
+                                 &txv);
+    if ( EFI_ERROR(status) )
+        blexit(L"Unable to get TBOOT-Xen runtime variable");
+}
+
+static bool_t __init tboot_present(void)
+{
+    return (txv.revision == EFI_TBOOT_XEN_REV);
+}
+
+static void __init tboot_get_config(struct file *file)
+{
+    EFI_STATUS status;
+
+    file->addr = min(1UL << (32 + PAGE_SHIFT),
+                     HYPERVISOR_VIRT_END - DIRECTMAP_VIRT_START);
+    status = efi_bs->AllocatePages(AllocateMaxAddress, EfiLoaderData,
+                                   PFN_UP(txv.xen_config_size), &file->addr);
+    if ( EFI_ERROR(status) )
+        blexit(L"Unable to allocate memory for TBOOT provided config");
+
+    memcpy(file->ptr, txv.xen_config, txv.xen_config_size);
+    file->size = txv.xen_config_size;
+}
+
+static void __init tboot_post_launch(void *ets)
+{
+    g_efi_tboot_shared = ets;
+
+    efi_arch_post_exit_boot();
+    for( ; ; ); /* not reached */
+}
+
+static void __init tboot_begin_launch(void)
+{
+    xtd.kernel = kernel.ptr;
+    xtd.kernel_size = kernel.size;
+    xtd.ramdisk = ramdisk.ptr;
+    xtd.ramdisk_size = ramdisk.size;
+    xtd.memory_map = xtd_memmap;
+    xtd.memory_map_size = efi_memmap_size;
+    xtd.memory_desc_size = efi_mdesc_size;
+    xtd.post_launch_cb = (uint64_t)tboot_post_launch;
+
+    __asm__ __volatile__ (
+                   "call *%%rax\n\t"
+                   :
+                   : "a" (txv.begin_launch_cb), "c" (&xtd));
+    /* no return */
+}
+
 static void __init efi_set_gop_mode(EFI_GRAPHICS_OUTPUT_PROTOCOL *gop, UINTN gop_mode)
 {
     EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *mode_info;
@@ -893,6 +992,9 @@ static void __init efi_exit_boot(EFI_HAN
     if ( EFI_ERROR(status) )
         PrintErrMesg(L"Cannot exit boot services", status);
 
+    /* Save unadjusted memmap pointer for Xen/TBOOT data */
+    xtd_memmap = efi_memmap;
+
     /* Adjust pointers into EFI. */
     efi_ct = (void *)efi_ct + DIRECTMAP_VIRT_START;
 #ifdef USE_SET_VIRTUAL_ADDRESS_MAP
@@ -924,7 +1026,7 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SY
     static EFI_GUID __initdata shim_lock_guid = SHIM_LOCK_PROTOCOL_GUID;
     EFI_LOADED_IMAGE *loaded_image;
     EFI_STATUS status;
-    unsigned int i, argc;
+    unsigned int i, argc = 0;
     CHAR16 **argv, *file_name, *cfg_file_name = NULL, *options = NULL;
     UINTN gop_mode = ~0;
     EFI_SHIM_LOCK_PROTOCOL *shim_lock;
@@ -945,7 +1047,7 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SY
 
     efi_arch_load_addr_check(loaded_image);
 
-    if ( use_cfg_file )
+    if ( use_cfg_file && !tboot_present() )
     {
         argc = get_argv(0, NULL, loaded_image->LoadOptions,
                         loaded_image->LoadOptionsSize, NULL);
@@ -1004,6 +1106,9 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SY
 
     efi_arch_relocate_image(0);
 
+    /* Find the Xen/TBOOT RT variable if booted through TBOOT */
+    efi_xen_tboot_variable();
+
     if ( use_cfg_file )
     {
         EFI_FILE_HANDLE dir_handle;
@@ -1021,7 +1126,9 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SY
         dir_handle = get_parent_handle(loaded_image, &file_name);
 
         /* Read and parse the config file. */
-        if ( !cfg_file_name )
+        if ( tboot_present() )
+            tboot_get_config(&cfg);
+        else if ( !cfg_file_name )
         {
             CHAR16 *tail;
 
@@ -1055,6 +1162,9 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SY
             name.s = get_value(&cfg, "global", "chain");
             if ( !name.s )
                 break;
+            /* Chain loaded configs not OK in TBOOT land */
+            if ( tboot_present() )
+                break;
             efi_bs->FreePages(cfg.addr, PFN_UP(cfg.size));
             cfg.addr = 0;
             if ( !read_file(dir_handle, s2w(&name), &cfg, NULL) )
@@ -1147,6 +1257,10 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SY
 
     efi_exit_boot(ImageHandle, SystemTable);
 
+    /* Do the measured launch, end up back here if it fails. */
+    if ( tboot_present() )
+        tboot_begin_launch();
+
     efi_arch_post_exit_boot();
     for( ; ; ); /* not reached */
 }
Index: xen-4.7.1/xen/arch/x86/tboot.c
===================================================================
--- xen-4.7.1.orig/xen/arch/x86/tboot.c
+++ xen-4.7.1/xen/arch/x86/tboot.c
@@ -18,6 +18,9 @@
 static unsigned long __initdata opt_tboot_pa;
 integer_param("tboot", opt_tboot_pa);
 
+/* Global pointer to shared data passed by EFI boot code. */
+void *g_efi_tboot_shared;
+
 /* Global pointer to shared data; NULL means no measured launch. */
 tboot_shared_t *g_tboot_shared;
 
Index: xen-4.7.1/xen/include/asm-x86/tboot.h
===================================================================
--- xen-4.7.1.orig/xen/include/asm-x86/tboot.h
+++ xen-4.7.1/xen/include/asm-x86/tboot.h
@@ -78,6 +78,13 @@ typedef struct __packed {
     uint64_t kernel_s3_resume_vector;
 } tboot_acpi_sleep_info_t;
 
+#define TB_RESMEM_BLOCKS        128
+
+typedef struct __packed {
+    uint64_t addr;
+    uint64_t length;
+} reserve_map_t;
+
 typedef struct __packed {
     /* version 3+ fields: */
     uuid_t    uuid;              /* {663C8DFF-E8B3-4b82-AABF-19EA4D057A08} */
@@ -102,6 +109,10 @@ typedef struct __packed {
     uint32_t  flags;
     uint64_t  ap_wake_addr;      /* phys addr of kernel/VMM SIPI vector */
     uint32_t  ap_wake_trigger;   /* kernel/VMM writes APIC ID to wake AP */
+    /* version 7+ fields */
+                                 /* reserve mem blocks to adjust dom0 E820 */
+    uint64_t      reserve_map_count;
+    reserve_map_t reserve_map[TB_RESMEM_BLOCKS];
 } tboot_shared_t;
 
 #define TB_SHUTDOWN_REBOOT      0