Blame view

cmd/bootefi.c 12.6 KB
b9939336d   Alexander Graf   efi_loader: Add "...
1
2
3
4
5
6
7
  /*
   *  EFI application loader
   *
   *  Copyright (c) 2016 Alexander Graf
   *
   *  SPDX-License-Identifier:     GPL-2.0+
   */
d78e40d65   Heinrich Schuchardt   efi_selftest: all...
8
  #include <charset.h>
b9939336d   Alexander Graf   efi_loader: Add "...
9
10
  #include <common.h>
  #include <command.h>
9d922450a   Simon Glass   dm: Use dm.h head...
11
  #include <dm.h>
b9939336d   Alexander Graf   efi_loader: Add "...
12
  #include <efi_loader.h>
d78e40d65   Heinrich Schuchardt   efi_selftest: all...
13
  #include <efi_selftest.h>
b9939336d   Alexander Graf   efi_loader: Add "...
14
  #include <errno.h>
b08c8c487   Masahiro Yamada   libfdt: move head...
15
16
  #include <linux/libfdt.h>
  #include <linux/libfdt_env.h>
ad0c1a3d2   Alexander Graf   efi_loader: Put f...
17
  #include <memalign.h>
0d9d501f3   Alexander Graf   efi_loader: Use s...
18
  #include <asm/global_data.h>
e275458c2   Simon Glass   efi: Fix missing ...
19
20
  #include <asm-generic/sections.h>
  #include <linux/linkage.h>
0d9d501f3   Alexander Graf   efi_loader: Use s...
21
22
  
  DECLARE_GLOBAL_DATA_PTR;
b9939336d   Alexander Graf   efi_loader: Add "...
23

7cbc12415   Heinrich Schuchardt   efi_loader: inita...
24
  static uint8_t efi_obj_list_initalized;
95c5553ea   Rob Clark   efi_loader: refac...
25
26
  static struct efi_device_path *bootefi_image_path;
  static struct efi_device_path *bootefi_device_path;
b9939336d   Alexander Graf   efi_loader: Add "...
27

7cbc12415   Heinrich Schuchardt   efi_loader: inita...
28
29
30
31
  /* Initialize and populate EFI object list */
  static void efi_init_obj_list(void)
  {
  	efi_obj_list_initalized = 1;
05ef48a24   Heinrich Schuchardt   efi_driver: EFI b...
32
33
  	/* Initialize EFI driver uclass */
  	efi_driver_init();
7cbc12415   Heinrich Schuchardt   efi_loader: inita...
34
35
36
37
38
39
40
  	efi_console_register();
  #ifdef CONFIG_PARTITIONS
  	efi_disk_register();
  #endif
  #if defined(CONFIG_LCD) || defined(CONFIG_DM_VIDEO)
  	efi_gop_register();
  #endif
3b3ea2c56   Michal Simek   Kconfig: cmd: Mak...
41
  #ifdef CONFIG_CMD_NET
95c5553ea   Rob Clark   efi_loader: refac...
42
  	efi_net_register();
7cbc12415   Heinrich Schuchardt   efi_loader: inita...
43
44
45
46
  #endif
  #ifdef CONFIG_GENERATE_SMBIOS_TABLE
  	efi_smbios_register();
  #endif
b3d609004   Heinrich Schuchardt   efi_loader: imple...
47
  	efi_watchdog_register();
7cbc12415   Heinrich Schuchardt   efi_loader: inita...
48
49
50
51
52
  
  	/* Initialize EFI runtime services */
  	efi_reset_system_init();
  	efi_get_time_init();
  }
d78e40d65   Heinrich Schuchardt   efi_selftest: all...
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
  /*
   * Set the load options of an image from an environment variable.
   *
   * @loaded_image_info:	the image
   * @env_var:		name of the environment variable
   */
  static void set_load_options(struct efi_loaded_image *loaded_image_info,
  			     const char *env_var)
  {
  	size_t size;
  	const char *env = env_get(env_var);
  
  	loaded_image_info->load_options = NULL;
  	loaded_image_info->load_options_size = 0;
  	if (!env)
  		return;
  	size = strlen(env) + 1;
  	loaded_image_info->load_options = calloc(size, sizeof(u16));
  	if (!loaded_image_info->load_options) {
  		printf("ERROR: Out of memory
  ");
  		return;
  	}
  	utf8_to_utf16(loaded_image_info->load_options, (u8 *)env, size);
  	loaded_image_info->load_options_size = size * 2;
  }
0d9d501f3   Alexander Graf   efi_loader: Use s...
79
80
81
  static void *copy_fdt(void *fdt)
  {
  	u64 fdt_size = fdt_totalsize(fdt);
ad0c1a3d2   Alexander Graf   efi_loader: Put f...
82
83
  	unsigned long fdt_ram_start = -1L, fdt_pages;
  	u64 new_fdt_addr;
0d9d501f3   Alexander Graf   efi_loader: Use s...
84
  	void *new_fdt;
ad0c1a3d2   Alexander Graf   efi_loader: Put f...
85
  	int i;
0d9d501f3   Alexander Graf   efi_loader: Use s...
86

ad0c1a3d2   Alexander Graf   efi_loader: Put f...
87
88
89
          for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
                  u64 ram_start = gd->bd->bi_dram[i].start;
                  u64 ram_size = gd->bd->bi_dram[i].size;
0d9d501f3   Alexander Graf   efi_loader: Use s...
90

ad0c1a3d2   Alexander Graf   efi_loader: Put f...
91
92
93
94
95
96
97
98
  		if (!ram_size)
  			continue;
  
  		if (ram_start < fdt_ram_start)
  			fdt_ram_start = ram_start;
  	}
  
  	/* Give us at least 4kb breathing room */
a44bffcc9   xypron.glpk@gmx.de   efi_loader: use E...
99
  	fdt_size = ALIGN(fdt_size + 4096, EFI_PAGE_SIZE);
ad0c1a3d2   Alexander Graf   efi_loader: Put f...
100
101
102
103
  	fdt_pages = fdt_size >> EFI_PAGE_SHIFT;
  
  	/* Safe fdt location is at 128MB */
  	new_fdt_addr = fdt_ram_start + (128 * 1024 * 1024) + fdt_size;
17ff6f02f   Heinrich Schuchardt   efi_loader: store...
104
  	if (efi_allocate_pages(1, EFI_RUNTIME_SERVICES_DATA, fdt_pages,
ad0c1a3d2   Alexander Graf   efi_loader: Put f...
105
106
  			       &new_fdt_addr) != EFI_SUCCESS) {
  		/* If we can't put it there, put it somewhere */
a44bffcc9   xypron.glpk@gmx.de   efi_loader: use E...
107
  		new_fdt_addr = (ulong)memalign(EFI_PAGE_SIZE, fdt_size);
17ff6f02f   Heinrich Schuchardt   efi_loader: store...
108
  		if (efi_allocate_pages(1, EFI_RUNTIME_SERVICES_DATA, fdt_pages,
85a6e9b3c   Alexander Graf   efi_loader: Add c...
109
110
111
112
113
  				       &new_fdt_addr) != EFI_SUCCESS) {
  			printf("ERROR: Failed to reserve space for FDT
  ");
  			return NULL;
  		}
ad0c1a3d2   Alexander Graf   efi_loader: Put f...
114
  	}
85a6e9b3c   Alexander Graf   efi_loader: Add c...
115

ad0c1a3d2   Alexander Graf   efi_loader: Put f...
116
  	new_fdt = (void*)(ulong)new_fdt_addr;
0d9d501f3   Alexander Graf   efi_loader: Use s...
117
118
119
120
121
  	memcpy(new_fdt, fdt, fdt_totalsize(fdt));
  	fdt_set_totalsize(new_fdt, fdt_size);
  
  	return new_fdt;
  }
3eb0841be   Heinrich Schuchardt   efi_loader: consi...
122
  static efi_status_t efi_do_enter(
2074f7006   Heinrich Schuchardt   efi_loader: consi...
123
  			efi_handle_t image_handle, struct efi_system_table *st,
c6fa5df6a   Alexander Graf   efi_loader: Alway...
124
125
126
  			EFIAPI efi_status_t (*entry)(
  				efi_handle_t image_handle,
  				struct efi_system_table *st))
b06d8ac39   xypron.glpk@gmx.de   bootefi: allow re...
127
128
129
130
131
132
133
134
  {
  	efi_status_t ret = EFI_LOAD_ERROR;
  
  	if (entry)
  		ret = entry(image_handle, st);
  	st->boottime->exit(image_handle, ret, 0, NULL);
  	return ret;
  }
ec6617c39   Alison Wang   armv8: Support lo...
135
  #ifdef CONFIG_ARM64
c6fa5df6a   Alexander Graf   efi_loader: Alway...
136
  static efi_status_t efi_run_in_el2(EFIAPI efi_status_t (*entry)(
2074f7006   Heinrich Schuchardt   efi_loader: consi...
137
138
  			efi_handle_t image_handle, struct efi_system_table *st),
  			efi_handle_t image_handle, struct efi_system_table *st)
ec6617c39   Alison Wang   armv8: Support lo...
139
140
141
  {
  	/* Enable caches again */
  	dcache_enable();
b06d8ac39   xypron.glpk@gmx.de   bootefi: allow re...
142
  	return efi_do_enter(image_handle, st, entry);
ec6617c39   Alison Wang   armv8: Support lo...
143
144
  }
  #endif
b9939336d   Alexander Graf   efi_loader: Add "...
145
146
147
148
  /*
   * Load an EFI payload into a newly allocated piece of memory, register all
   * EFI objects it would want to access and jump to it.
   */
3eb0841be   Heinrich Schuchardt   efi_loader: consi...
149
150
151
  static efi_status_t do_bootefi_exec(void *efi, void *fdt,
  				    struct efi_device_path *device_path,
  				    struct efi_device_path *image_path)
b9939336d   Alexander Graf   efi_loader: Add "...
152
  {
95c5553ea   Rob Clark   efi_loader: refac...
153
154
  	struct efi_loaded_image loaded_image_info = {};
  	struct efi_object loaded_image_info_obj = {};
bf19273e8   Rob Clark   efi_loader: Add m...
155
  	struct efi_device_path *memdp = NULL;
95c5553ea   Rob Clark   efi_loader: refac...
156
  	ulong ret;
c6fa5df6a   Alexander Graf   efi_loader: Alway...
157
158
  	EFIAPI efi_status_t (*entry)(efi_handle_t image_handle,
  				     struct efi_system_table *st);
b9939336d   Alexander Graf   efi_loader: Add "...
159
  	ulong fdt_pages, fdt_size, fdt_start, fdt_end;
f4f9993f7   Alexander Graf   efi_loader: Fix c...
160
  	const efi_guid_t fdt_guid = EFI_FDT_GUID;
dea2174d9   Alexander Graf   efi_loader: Call ...
161
  	bootm_headers_t img = { 0 };
b9939336d   Alexander Graf   efi_loader: Add "...
162

bf19273e8   Rob Clark   efi_loader: Add m...
163
164
165
166
167
168
169
170
171
172
173
174
175
176
  	/*
  	 * Special case for efi payload not loaded from disk, such as
  	 * 'bootefi hello' or for example payload loaded directly into
  	 * memory via jtag/etc:
  	 */
  	if (!device_path && !image_path) {
  		printf("WARNING: using memory device/image path, this may confuse some payloads!
  ");
  		/* actual addresses filled in after efi_load_pe() */
  		memdp = efi_dp_from_mem(0, 0, 0);
  		device_path = image_path = memdp;
  	} else {
  		assert(device_path && image_path);
  	}
95c5553ea   Rob Clark   efi_loader: refac...
177
178
179
180
181
182
  	/* Initialize and populate EFI object list */
  	if (!efi_obj_list_initalized)
  		efi_init_obj_list();
  
  	efi_setup_loaded_image(&loaded_image_info, &loaded_image_info_obj,
  			       device_path, image_path);
b9939336d   Alexander Graf   efi_loader: Add "...
183
184
185
186
187
  	/*
  	 * gd lives in a fixed register which may get clobbered while we execute
  	 * the payload. So save it here and restore it on every callback entry
  	 */
  	efi_save_gd();
1c39809b9   Alexander Graf   efi_loader: Pass ...
188
  	if (fdt && !fdt_check_header(fdt)) {
dea2174d9   Alexander Graf   efi_loader: Call ...
189
  		/* Prepare fdt for payload */
0d9d501f3   Alexander Graf   efi_loader: Use s...
190
191
192
  		fdt = copy_fdt(fdt);
  
  		if (image_setup_libfdt(&img, fdt, 0, NULL)) {
dea2174d9   Alexander Graf   efi_loader: Call ...
193
194
195
196
197
198
  			printf("ERROR: Failed to process device tree
  ");
  			return -EINVAL;
  		}
  
  		/* Link to it in the efi tables */
f4f9993f7   Alexander Graf   efi_loader: Fix c...
199
  		efi_install_configuration_table(&fdt_guid, fdt);
b9939336d   Alexander Graf   efi_loader: Add "...
200
201
  
  		/* And reserve the space in the memory map */
0d9d501f3   Alexander Graf   efi_loader: Use s...
202
203
  		fdt_start = ((ulong)fdt) & ~EFI_PAGE_MASK;
  		fdt_end = ((ulong)fdt) + fdt_totalsize(fdt);
b9939336d   Alexander Graf   efi_loader: Add "...
204
205
206
207
208
209
  		fdt_size = (fdt_end - fdt_start) + EFI_PAGE_MASK;
  		fdt_pages = fdt_size >> EFI_PAGE_SHIFT;
  		/* Give a bootloader the chance to modify the device tree */
  		fdt_pages += 2;
  		efi_add_memory_map(fdt_start, fdt_pages,
  				   EFI_BOOT_SERVICES_DATA, true);
b9939336d   Alexander Graf   efi_loader: Add "...
210
  	} else {
1c39809b9   Alexander Graf   efi_loader: Pass ...
211
212
  		printf("WARNING: Invalid device tree, expect boot to fail
  ");
f4f9993f7   Alexander Graf   efi_loader: Fix c...
213
  		efi_install_configuration_table(&fdt_guid, NULL);
b9939336d   Alexander Graf   efi_loader: Add "...
214
  	}
b57f48a87   Heinrich Schuchardt   efi_loader: use b...
215
216
  	/* Transfer environment variable bootargs as load options */
  	set_load_options(&loaded_image_info, "bootargs");
b9939336d   Alexander Graf   efi_loader: Add "...
217
218
  	/* Load the EFI payload */
  	entry = efi_load_pe(efi, &loaded_image_info);
95c5553ea   Rob Clark   efi_loader: refac...
219
220
221
222
  	if (!entry) {
  		ret = -ENOENT;
  		goto exit;
  	}
80a4800ee   Alexander Graf   efi_loader: Allow...
223

bf19273e8   Rob Clark   efi_loader: Add m...
224
225
226
227
228
229
230
  	if (memdp) {
  		struct efi_device_path_memory *mdp = (void *)memdp;
  		mdp->memory_type = loaded_image_info.image_code_type;
  		mdp->start_address = (uintptr_t)loaded_image_info.image_base;
  		mdp->end_address = mdp->start_address +
  				loaded_image_info.image_size;
  	}
ad644e7c1   Rob Clark   efi_loader: efi v...
231
232
233
  	/* we don't support much: */
  	env_set("efi_8be4df61-93ca-11d2-aa0d-00e098032b8c_OsIndicationsSupported",
  		"{ro,boot}(blob)0000000000000000");
b9939336d   Alexander Graf   efi_loader: Add "...
234
  	/* Call our payload! */
edcef3ba1   Alexander Graf   efi_loader: Move ...
235
236
  	debug("%s:%d Jumping to 0x%lx
  ", __func__, __LINE__, (long)entry);
a86aeaf22   Alexander Graf   efi_loader: Add e...
237
238
  
  	if (setjmp(&loaded_image_info.exit_jmp)) {
95c5553ea   Rob Clark   efi_loader: refac...
239
  		ret = loaded_image_info.exit_status;
95c5553ea   Rob Clark   efi_loader: refac...
240
  		goto exit;
a86aeaf22   Alexander Graf   efi_loader: Add e...
241
  	}
69bd459d3   Alexander Graf   efi_loader: AArch...
242
243
244
245
246
  #ifdef CONFIG_ARM64
  	/* On AArch64 we need to make sure we call our payload in < EL3 */
  	if (current_el() == 3) {
  		smp_kick_all_cpus();
  		dcache_disable();	/* flush cache before switch to EL2 */
ec6617c39   Alison Wang   armv8: Support lo...
247
248
  
  		/* Move into EL2 and keep running there */
ea54ad592   Heinrich Schuchardt   efi_loader: pass ...
249
250
  		armv8_switch_to_el2((ulong)entry,
  				    (ulong)&loaded_image_info_obj.handle,
7c5e1feb1   Alison Wang   armv8: aarch64: F...
251
  				    (ulong)&systab, 0, (ulong)efi_run_in_el2,
ec6617c39   Alison Wang   armv8: Support lo...
252
253
254
255
  				    ES_TO_AARCH64);
  
  		/* Should never reach here, efi exits with longjmp */
  		while (1) { }
69bd459d3   Alexander Graf   efi_loader: AArch...
256
257
  	}
  #endif
ea54ad592   Heinrich Schuchardt   efi_loader: pass ...
258
  	ret = efi_do_enter(loaded_image_info_obj.handle, &systab, entry);
95c5553ea   Rob Clark   efi_loader: refac...
259
260
261
262
263
264
  
  exit:
  	/* image has returned, loaded-image obj goes *poof*: */
  	list_del(&loaded_image_info_obj.link);
  
  	return ret;
b9939336d   Alexander Graf   efi_loader: Add "...
265
  }
9975fe96b   Rob Clark   efi_loader: add b...
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
  static int do_bootefi_bootmgr_exec(unsigned long fdt_addr)
  {
  	struct efi_device_path *device_path, *file_path;
  	void *addr;
  	efi_status_t r;
  
  	/* Initialize and populate EFI object list */
  	if (!efi_obj_list_initalized)
  		efi_init_obj_list();
  
  	/*
  	 * gd lives in a fixed register which may get clobbered while we execute
  	 * the payload. So save it here and restore it on every callback entry
  	 */
  	efi_save_gd();
  
  	addr = efi_bootmgr_load(&device_path, &file_path);
  	if (!addr)
  		return 1;
  
  	printf("## Starting EFI application at %p ...
  ", addr);
  	r = do_bootefi_exec(addr, (void *)fdt_addr, device_path, file_path);
  	printf("## Application terminated, r = %lu
  ",
  	       r & ~EFI_ERROR_MASK);
  
  	if (r != EFI_SUCCESS)
  		return 1;
  
  	return 0;
  }
b9939336d   Alexander Graf   efi_loader: Add "...
298
299
300
  /* Interpreter command to boot an arbitrary EFI image from memory */
  static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
  {
1c39809b9   Alexander Graf   efi_loader: Pass ...
301
302
  	char *saddr, *sfdt;
  	unsigned long addr, fdt_addr = 0;
3eb0841be   Heinrich Schuchardt   efi_loader: consi...
303
  	efi_status_t r;
b9939336d   Alexander Graf   efi_loader: Add "...
304
305
  
  	if (argc < 2)
3c1dcef62   Bin Meng   cmd: efi_loader: ...
306
  		return CMD_RET_USAGE;
c7ae3dfdc   Simon Glass   efi: Add support ...
307
308
  #ifdef CONFIG_CMD_BOOTEFI_HELLO
  	if (!strcmp(argv[1], "hello")) {
5e44489bc   Heinrich Schuchardt   efi_loader: renam...
309
  		ulong size = __efi_helloworld_end - __efi_helloworld_begin;
b9939336d   Alexander Graf   efi_loader: Add "...
310

51c533fdc   Heinrich Schuchardt   efi_loader: boote...
311
312
313
314
315
  		saddr = env_get("loadaddr");
  		if (saddr)
  			addr = simple_strtoul(saddr, NULL, 16);
  		else
  			addr = CONFIG_SYS_LOAD_ADDR;
5e44489bc   Heinrich Schuchardt   efi_loader: renam...
316
  		memcpy((char *)addr, __efi_helloworld_begin, size);
c7ae3dfdc   Simon Glass   efi: Add support ...
317
318
  	} else
  #endif
623b3a579   Heinrich Schuchardt   efi_selftest: pro...
319
320
  #ifdef CONFIG_CMD_BOOTEFI_SELFTEST
  	if (!strcmp(argv[1], "selftest")) {
7aca68ca0   Heinrich Schuchardt   efi_loader: reena...
321
322
  		struct efi_loaded_image loaded_image_info = {};
  		struct efi_object loaded_image_info_obj = {};
f972dc140   Heinrich Schuchardt   efi_selftest: pro...
323
324
325
326
327
  		/* Construct a dummy device path. */
  		bootefi_device_path = efi_dp_from_mem(EFI_RESERVED_MEMORY_TYPE,
  						      (uintptr_t)&efi_selftest,
  						      (uintptr_t)&efi_selftest);
  		bootefi_image_path = efi_dp_from_file(NULL, 0, "\\selftest");
7aca68ca0   Heinrich Schuchardt   efi_loader: reena...
328
329
330
  		efi_setup_loaded_image(&loaded_image_info,
  				       &loaded_image_info_obj,
  				       bootefi_device_path, bootefi_image_path);
623b3a579   Heinrich Schuchardt   efi_selftest: pro...
331
332
333
334
335
336
337
338
339
  		/*
  		 * gd lives in a fixed register which may get clobbered while we
  		 * execute the payload. So save it here and restore it on every
  		 * callback entry
  		 */
  		efi_save_gd();
  		/* Initialize and populate EFI object list */
  		if (!efi_obj_list_initalized)
  			efi_init_obj_list();
d78e40d65   Heinrich Schuchardt   efi_selftest: all...
340
341
342
  		/* Transfer environment variable efi_selftest as load options */
  		set_load_options(&loaded_image_info, "efi_selftest");
  		/* Execute the test */
ea54ad592   Heinrich Schuchardt   efi_loader: pass ...
343
  		r = efi_selftest(loaded_image_info_obj.handle, &systab);
c2b53902c   Heinrich Schuchardt   efi_selftest: cor...
344
  		efi_restore_gd();
d78e40d65   Heinrich Schuchardt   efi_selftest: all...
345
  		free(loaded_image_info.load_options);
c2b53902c   Heinrich Schuchardt   efi_selftest: cor...
346
347
  		list_del(&loaded_image_info_obj.link);
  		return r != EFI_SUCCESS;
623b3a579   Heinrich Schuchardt   efi_selftest: pro...
348
349
  	} else
  #endif
9975fe96b   Rob Clark   efi_loader: add b...
350
351
352
353
354
355
356
357
  	if (!strcmp(argv[1], "bootmgr")) {
  		unsigned long fdt_addr = 0;
  
  		if (argc > 2)
  			fdt_addr = simple_strtoul(argv[2], NULL, 16);
  
  		return do_bootefi_bootmgr_exec(fdt_addr);
  	} else {
c7ae3dfdc   Simon Glass   efi: Add support ...
358
  		saddr = argv[1];
b9939336d   Alexander Graf   efi_loader: Add "...
359

c7ae3dfdc   Simon Glass   efi: Add support ...
360
  		addr = simple_strtoul(saddr, NULL, 16);
49db1cb8c   Heinrich Schuchardt   efi_loader: catch...
361
362
363
  		/* Check that a numeric value was passed */
  		if (!addr && *saddr != '0')
  			return CMD_RET_USAGE;
c7ae3dfdc   Simon Glass   efi: Add support ...
364
365
366
367
368
  
  		if (argc > 2) {
  			sfdt = argv[2];
  			fdt_addr = simple_strtoul(sfdt, NULL, 16);
  		}
1c39809b9   Alexander Graf   efi_loader: Pass ...
369
  	}
5ee31baf8   Simon Glass   efi: Fix debug me...
370
371
  	printf("## Starting EFI application at %08lx ...
  ", addr);
95c5553ea   Rob Clark   efi_loader: refac...
372
373
  	r = do_bootefi_exec((void *)addr, (void *)fdt_addr,
  			    bootefi_device_path, bootefi_image_path);
1da1bac47   xypron.glpk@gmx.de   efi_loader: provi...
374
375
376
  	printf("## Application terminated, r = %lu
  ",
  	       r & ~EFI_ERROR_MASK);
b9939336d   Alexander Graf   efi_loader: Add "...
377

1da1bac47   xypron.glpk@gmx.de   efi_loader: provi...
378
379
380
381
  	if (r != EFI_SUCCESS)
  		return 1;
  	else
  		return 0;
b9939336d   Alexander Graf   efi_loader: Add "...
382
383
384
385
  }
  
  #ifdef CONFIG_SYS_LONGHELP
  static char bootefi_help_text[] =
1c39809b9   Alexander Graf   efi_loader: Pass ...
386
387
388
389
390
391
  	"<image address> [fdt address]
  "
  	"  - boot EFI payload stored at address <image address>.
  "
  	"    If specified, the device tree located at <fdt address> gets
  "
c7ae3dfdc   Simon Glass   efi: Add support ...
392
393
394
  	"    exposed as EFI configuration table.
  "
  #ifdef CONFIG_CMD_BOOTEFI_HELLO
623b3a579   Heinrich Schuchardt   efi_selftest: pro...
395
396
397
398
399
400
401
402
403
404
  	"bootefi hello
  "
  	"  - boot a sample Hello World application stored within U-Boot
  "
  #endif
  #ifdef CONFIG_CMD_BOOTEFI_SELFTEST
  	"bootefi selftest
  "
  	"  - boot an EFI selftest application stored within U-Boot
  "
d78e40d65   Heinrich Schuchardt   efi_selftest: all...
405
406
407
408
  	"    Use environment variable efi_selftest to select a single test.
  "
  	"    Use 'setenv efi_selftest list' to enumerate all tests.
  "
c7ae3dfdc   Simon Glass   efi: Add support ...
409
  #endif
f623e07f0   Heinrich Schuchardt   efi_loader: fix t...
410
411
  	"bootefi bootmgr [fdt addr]
  "
9975fe96b   Rob Clark   efi_loader: add b...
412
413
414
415
416
417
418
419
  	"  - load and boot EFI payload based on BootOrder/BootXXXX variables.
  "
  	"
  "
  	"    If specified, the device tree located at <fdt address> gets
  "
  	"    exposed as EFI configuration table.
  ";
b9939336d   Alexander Graf   efi_loader: Add "...
420
421
422
  #endif
  
  U_BOOT_CMD(
1c39809b9   Alexander Graf   efi_loader: Pass ...
423
  	bootefi, 3, 0, do_bootefi,
92dfd9221   Sergey Kubushyn   cmd: bootefi: cos...
424
  	"Boots an EFI payload from memory",
b9939336d   Alexander Graf   efi_loader: Add "...
425
426
  	bootefi_help_text
  );
0f4060ebc   Alexander Graf   efi_loader: Pass ...
427

95c5553ea   Rob Clark   efi_loader: refac...
428
  static int parse_partnum(const char *devnr)
0f4060ebc   Alexander Graf   efi_loader: Pass ...
429
  {
95c5553ea   Rob Clark   efi_loader: refac...
430
431
432
433
  	const char *str = strchr(devnr, ':');
  	if (str) {
  		str++;
  		return simple_strtoul(str, NULL, 16);
f9d334bdf   Alexander Graf   efi_loader: disk:...
434
  	}
95c5553ea   Rob Clark   efi_loader: refac...
435
436
  	return 0;
  }
f9d334bdf   Alexander Graf   efi_loader: disk:...
437

95c5553ea   Rob Clark   efi_loader: refac...
438
439
440
441
  void efi_set_bootdev(const char *dev, const char *devnr, const char *path)
  {
  	char filename[32] = { 0 }; /* dp->str is u16[32] long */
  	char *s;
f9d334bdf   Alexander Graf   efi_loader: disk:...
442

95c5553ea   Rob Clark   efi_loader: refac...
443
444
445
  	if (strcmp(dev, "Net")) {
  		struct blk_desc *desc;
  		int part;
8c3df0bf2   Alexander Graf   efi_loader: Add e...
446

95c5553ea   Rob Clark   efi_loader: refac...
447
  		desc = blk_get_dev(dev, simple_strtol(devnr, NULL, 10));
8300be612   Stefan Roese   efi_loader: Exit ...
448
449
  		if (!desc)
  			return;
95c5553ea   Rob Clark   efi_loader: refac...
450
  		part = parse_partnum(devnr);
0f4060ebc   Alexander Graf   efi_loader: Pass ...
451

95c5553ea   Rob Clark   efi_loader: refac...
452
453
  		bootefi_device_path = efi_dp_from_part(desc, part);
  	} else {
3b3ea2c56   Michal Simek   Kconfig: cmd: Mak...
454
  #ifdef CONFIG_CMD_NET
95c5553ea   Rob Clark   efi_loader: refac...
455
456
457
  		bootefi_device_path = efi_dp_from_eth();
  #endif
  	}
c07ad7c03   Alexander Graf   efi_loader: Pass ...
458

9975fe96b   Rob Clark   efi_loader: add b...
459
460
  	if (!path)
  		return;
492716662   Alexander Graf   efi_loader: Make ...
461
462
  	if (strcmp(dev, "Net")) {
  		/* Add leading / to fs paths, because they're absolute */
95c5553ea   Rob Clark   efi_loader: refac...
463
  		snprintf(filename, sizeof(filename), "/%s", path);
492716662   Alexander Graf   efi_loader: Make ...
464
  	} else {
95c5553ea   Rob Clark   efi_loader: refac...
465
  		snprintf(filename, sizeof(filename), "%s", path);
492716662   Alexander Graf   efi_loader: Make ...
466
  	}
3e433e960   Rob Clark   efi_loader: EFI f...
467
  	/* DOS style file path: */
95c5553ea   Rob Clark   efi_loader: refac...
468
  	s = filename;
3e433e960   Rob Clark   efi_loader: EFI f...
469
470
  	while ((s = strchr(s, '/')))
  		*s++ = '\\';
95c5553ea   Rob Clark   efi_loader: refac...
471
  	bootefi_image_path = efi_dp_from_file(NULL, 0, filename);
0f4060ebc   Alexander Graf   efi_loader: Pass ...
472
  }