View | Details | Raw Unified | Return to bug 209821 | Differences between
and this patch

Collapse All | Expand All

(-)b/stand/efi/loader/arch/amd64/amd64_tramp.S (+52 lines)
Lines 61-66 amd64_tramp: Link Here
61
	ALIGN_TEXT
61
	ALIGN_TEXT
62
amd64_tramp_end:
62
amd64_tramp_end:
63
63
64
/*
65
 * void amd64_tramp_inline(uint64_t stack, uint64_t kernend,
66
 *			uint64_t modulep, uint64_t pagetable, uint64_t entry,
67
 *			uint64_t copy_dst, uint64_t copy_src, uint64_t copy_src_end)
68
 */
69
	.globl	amd64_tramp_inline
70
amd64_tramp_inline:
71
	cli			/* Make sure we don't get interrupted. */
72
73
	movq	%rsi,%r12	/* Stash the kernel values for later. */
74
	movq	%rdx,%r13
75
	movq	%rcx,%r14
76
	movq	%r8,%r15
77
78
	/* Copy the kernel from the staging area to the expected location
79
	 * in memory. The following code is equivalent to the efi_copy_finish
80
	 * function that amd64_tramp used to call. Inlining this code avoids
81
	 * a scenario when the system froze because efi_copy_finish
82
	 * overwrote its own code that just happened to be located somewhere
83
	 * in the destination range.
84
	 *
85
	 * while (copy_src < copy_src_end) *copy_dst++ = *copy_src++;
86
	 */
87
	movq	8(%rsp), %rax	/* rax = copy_src */
88
	movq	16(%rsp), %rcx	/* rcx = copy_src_end */
89
	cmpq	%rcx, %rax
90
	jnb	copy_done
91
	subq	%rax, %r9		/* r9 = copy_dst - copy_src */
92
loop:
93
	movq	(%rax), %rdx
94
	movq	%rdx, (%rax,%r9)
95
	addq	$8, %rax
96
	cmpq	%rax, %rcx
97
	ja	loop
98
copy_done:
99
100
	movq	%rdi,%rsp	/* Switch to our temporary stack. */
101
102
	pushq	%r12		/* Push kernend. */
103
	salq	$32,%r13	/* Shift modulep and push it. */
104
	pushq	%r13
105
	pushq	%r15		/* Push the entry address. */
106
	movq	%r14,%cr3	/* Switch page tables. */
107
	ret			/* "Return" to kernel entry. */
108
109
	ALIGN_TEXT
110
amd64_tramp_inline_end:
111
64
/* void multiboot2_exec(uint64_t entry, uint64_t multiboot_info, uint64_t stack) */
112
/* void multiboot2_exec(uint64_t entry, uint64_t multiboot_info, uint64_t stack) */
65
	.globl	multiboot2_exec
113
	.globl	multiboot2_exec
66
multiboot2_exec:
114
multiboot2_exec:
Lines 74-76 multiboot2_exec: Link Here
74
	.globl	amd64_tramp_size
122
	.globl	amd64_tramp_size
75
amd64_tramp_size:
123
amd64_tramp_size:
76
	.long	amd64_tramp_end-amd64_tramp
124
	.long	amd64_tramp_end-amd64_tramp
125
126
	.globl	amd64_tramp_inline_size
127
amd64_tramp_inline_size:
128
	.long	amd64_tramp_inline_end-amd64_tramp_inline
(-)b/stand/efi/loader/arch/amd64/elf64_freebsd.c (-9 / +33 lines)
Lines 84-94 static pml4_entry_t *PT4; Link Here
84
static pdp_entry_t *PT3;
84
static pdp_entry_t *PT3;
85
static pd_entry_t *PT2;
85
static pd_entry_t *PT2;
86
86
87
static void (*trampoline)(uint64_t stack, void *copy_finish, uint64_t kernend,
87
static void (*trampoline)(uint64_t stack, uint64_t kernend,
88
    uint64_t modulep, pml4_entry_t *pagetable, uint64_t entry);
88
	uint64_t modulep, pml4_entry_t *pagetable, uint64_t entry,
89
	uint64_t copy_dst, uint64_t copy_src, uint64_t copy_src_end);
89
90
90
extern uintptr_t amd64_tramp;
91
extern uintptr_t amd64_tramp_inline;
91
extern uint32_t amd64_tramp_size;
92
extern uint32_t amd64_tramp_inline_size;
92
93
93
/*
94
/*
94
 * There is an ELF kernel and one or more ELF modules loaded.
95
 * There is an ELF kernel and one or more ELF modules loaded.
Lines 101-106 elf64_exec(struct preloaded_file *fp) Link Here
101
	struct file_metadata	*md;
102
	struct file_metadata	*md;
102
	Elf_Ehdr 		*ehdr;
103
	Elf_Ehdr 		*ehdr;
103
	vm_offset_t		modulep, kernend, trampcode, trampstack;
104
	vm_offset_t		modulep, kernend, trampcode, trampstack;
105
	uint64_t		copy_dst, copy_src, copy_src_end;
106
	EFI_STATUS		status;
104
	int			err, i;
107
	int			err, i;
105
	ACPI_TABLE_RSDP		*rsdp;
108
	ACPI_TABLE_RSDP		*rsdp;
106
	char			buf[24];
109
	char			buf[24];
Lines 155-170 elf64_exec(struct preloaded_file *fp) Link Here
155
	ehdr = (Elf_Ehdr *)&(md->md_data);
158
	ehdr = (Elf_Ehdr *)&(md->md_data);
156
159
157
	trampcode = (vm_offset_t)0x0000000040000000;
160
	trampcode = (vm_offset_t)0x0000000040000000;
158
	err = BS->AllocatePages(AllocateMaxAddress, EfiLoaderData, 1,
161
	status = BS->AllocatePages(AllocateMaxAddress, EfiLoaderData, 1,
159
	    (EFI_PHYSICAL_ADDRESS *)&trampcode);
162
	    (EFI_PHYSICAL_ADDRESS *)&trampcode);
163
	if (EFI_ERROR(status)) {
164
		printf("Failed to allocate pages for trampoline code: %lu\n",
165
		    EFI_ERROR_CODE(status));
166
		return(ENOMEM);
167
	}
160
	bzero((void *)trampcode, EFI_PAGE_SIZE);
168
	bzero((void *)trampcode, EFI_PAGE_SIZE);
161
	trampstack = trampcode + EFI_PAGE_SIZE - 8;
169
	trampstack = trampcode + EFI_PAGE_SIZE - 8;
162
	bcopy((void *)&amd64_tramp, (void *)trampcode, amd64_tramp_size);
170
	bcopy((void *)&amd64_tramp_inline, (void *)trampcode, amd64_tramp_inline_size);
163
	trampoline = (void *)trampcode;
171
	trampoline = (void *)trampcode;
164
172
165
	PT4 = (pml4_entry_t *)0x0000000040000000;
173
	PT4 = (pml4_entry_t *)0x0000000040000000;
166
	err = BS->AllocatePages(AllocateMaxAddress, EfiLoaderData, 3,
174
	status = BS->AllocatePages(AllocateMaxAddress, EfiLoaderData, 3,
167
	    (EFI_PHYSICAL_ADDRESS *)&PT4);
175
	    (EFI_PHYSICAL_ADDRESS *)&PT4);
176
	if (EFI_ERROR(status)) {
177
		printf("Failed to allocate pages for PT4: %lu\n",
178
		    EFI_ERROR_CODE(status));
179
		return(ENOMEM);
180
	}
168
	bzero(PT4, 3 * EFI_PAGE_SIZE);
181
	bzero(PT4, 3 * EFI_PAGE_SIZE);
169
182
170
	PT3 = &PT4[512];
183
	PT3 = &PT4[512];
Lines 191-196 elf64_exec(struct preloaded_file *fp) Link Here
191
204
192
	printf("Start @ 0x%lx ...\n", ehdr->e_entry);
205
	printf("Start @ 0x%lx ...\n", ehdr->e_entry);
193
206
207
	/* Check the type of memory pages that will be overwritten
208
	 * by the trampoline and print a warning message for easier
209
	 * debugging. The memory map will most likely change until
210
	 * then, but I don't expect new reserved memory blocks to
211
	 * suddenly appear. */
212
	if (!efi_verify_destination_type()) {
213
		printf("Important memory pages may get overwritten!\n");
214
	}
215
194
	efi_time_fini();
216
	efi_time_fini();
195
	err = bi_load(fp->f_args, &modulep, &kernend, true);
217
	err = bi_load(fp->f_args, &modulep, &kernend, true);
196
	if (err != 0) {
218
	if (err != 0) {
Lines 200-207 elf64_exec(struct preloaded_file *fp) Link Here
200
222
201
	dev_cleanup();
223
	dev_cleanup();
202
224
203
	trampoline(trampstack, efi_copy_finish, kernend, modulep, PT4,
225
	efi_copy_get_locations(&copy_dst, &copy_src, &copy_src_end);
204
	    ehdr->e_entry);
226
227
	trampoline(trampstack, kernend, modulep, PT4,
228
	    ehdr->e_entry, copy_dst, copy_src, copy_src_end);
205
229
206
	panic("exec returned");
230
	panic("exec returned");
207
}
231
}
(-)b/stand/efi/loader/bootinfo.c (-1 / +5 lines)
Lines 444-449 bi_load(char *args, vm_offset_t *modulep, vm_offset_t *kernendp, bool exit_bs) Link Here
444
	vm_offset_t size;
444
	vm_offset_t size;
445
	char *rootdevname;
445
	char *rootdevname;
446
	int howto;
446
	int howto;
447
	int err;
447
#if defined(LOADER_FDT_SUPPORT)
448
#if defined(LOADER_FDT_SUPPORT)
448
	vm_offset_t dtbp;
449
	vm_offset_t dtbp;
449
	int dtb_size;
450
	int dtb_size;
Lines 539-545 bi_load(char *args, vm_offset_t *modulep, vm_offset_t *kernendp, bool exit_bs) Link Here
539
#ifdef LOADER_GELI_SUPPORT
540
#ifdef LOADER_GELI_SUPPORT
540
	geli_export_key_metadata(kfp);
541
	geli_export_key_metadata(kfp);
541
#endif
542
#endif
542
	bi_load_efi_data(kfp, exit_bs);
543
	err = bi_load_efi_data(kfp, exit_bs);
544
	if (err != 0) {
545
		return(err);
546
	}
543
547
544
	size = bi_copymodules(0);
548
	size = bi_copymodules(0);
545
	kernend = roundup(addr + size, PAGE_SIZE);
549
	kernend = roundup(addr + size, PAGE_SIZE);
(-)b/stand/efi/loader/copy.c (-1 / +88 lines)
Lines 208-214 efi_copy_init(void) Link Here
208
	 * memory: see elf64_exec() in
208
	 * memory: see elf64_exec() in
209
	 * boot/efi/loader/arch/amd64/elf64_freebsd.c.
209
	 * boot/efi/loader/arch/amd64/elf64_freebsd.c.
210
	 */
210
	 */
211
	staging = 1024*1024*1024;
211
	staging = 1024*1024*1024 - 1;
212
	status = BS->AllocatePages(AllocateMaxAddress, EfiLoaderData,
212
	status = BS->AllocatePages(AllocateMaxAddress, EfiLoaderData,
213
	    nr_pages, &staging);
213
	    nr_pages, &staging);
214
#else
214
#else
Lines 316-321 efi_copyin(const void *src, vm_offset_t dest, const size_t len) Link Here
316
	/* XXX: Callers do not check for failure. */
316
	/* XXX: Callers do not check for failure. */
317
	if (!efi_check_space(dest + stage_offset + len)) {
317
	if (!efi_check_space(dest + stage_offset + len)) {
318
		errno = ENOMEM;
318
		errno = ENOMEM;
319
		/* XXX: For now, it is better to stop
320
		 * booting instead of ignoring it. */
321
		panic("efi_copyin: Staging area is too small");
319
		return (-1);
322
		return (-1);
320
	}
323
	}
321
	bcopy(src, (void *)(dest + stage_offset), len);
324
	bcopy(src, (void *)(dest + stage_offset), len);
Lines 329-334 efi_copyout(const vm_offset_t src, void *dest, const size_t len) Link Here
329
	/* XXX: Callers do not check for failure. */
332
	/* XXX: Callers do not check for failure. */
330
	if (src + stage_offset + len > staging_end) {
333
	if (src + stage_offset + len > staging_end) {
331
		errno = ENOMEM;
334
		errno = ENOMEM;
335
		/* XXX: For now, it is better to stop
336
		 * booting instead of ignoring it. */
337
		panic("efi_copyout: Staging area is too small");
332
		return (-1);
338
		return (-1);
333
	}
339
	}
334
	bcopy((void *)(src + stage_offset), dest, len);
340
	bcopy((void *)(src + stage_offset), dest, len);
Lines 345-352 efi_readin(readin_handle_t fd, vm_offset_t dest, const size_t len) Link Here
345
		stage_offset_set = 1;
351
		stage_offset_set = 1;
346
	}
352
	}
347
353
354
	/* XXX: Callers don't seem to differentiate between a read failure
355
	 * from fd and an insufficient space in the staging area. */
348
	if (!efi_check_space(dest + stage_offset + len)) {
356
	if (!efi_check_space(dest + stage_offset + len)) {
349
		errno = ENOMEM;
357
		errno = ENOMEM;
358
		/* XXX: For now, at least print that the size of
359
		 * the staging area is at fault and should be larger. */
360
		printf("efi_readin: Staging area is too small\n");
350
		return (-1);
361
		return (-1);
351
	}
362
	}
352
	return (VECTX_READ(fd, (void *)(dest + stage_offset), len));
363
	return (VECTX_READ(fd, (void *)(dest + stage_offset), len));
Lines 364-366 efi_copy_finish(void) Link Here
364
	while (src < last)
375
	while (src < last)
365
		*dst++ = *src++;
376
		*dst++ = *src++;
366
}
377
}
378
379
void
380
efi_copy_get_locations(uint64_t *dst, uint64_t *src, uint64_t *src_end)
381
{
382
	*src = (uint64_t)staging;
383
	*dst = (uint64_t)(staging - stage_offset);
384
	*src_end = (uint64_t)staging_end;
385
}
386
387
bool
388
efi_verify_destination_type(void)
389
{
390
	EFI_MEMORY_DESCRIPTOR *map = NULL, *p;
391
	EFI_PHYSICAL_ADDRESS dest, dest_end;
392
	EFI_PHYSICAL_ADDRESS page_start, page_end, overlap_start, overlap_end;
393
	UINTN sz, key, dsz;
394
	UINT32 dver;
395
	EFI_STATUS status;
396
	int i, ndesc;
397
	bool safe;
398
399
	dest = staging - stage_offset;
400
	dest_end = dest + (staging_end - staging);
401
	safe = false;
402
403
	sz = 0;
404
405
	for (;;) {
406
		status = BS->GetMemoryMap(&sz, map, &key, &dsz, &dver);
407
		if (!EFI_ERROR(status))
408
			break;
409
410
		if (status != EFI_BUFFER_TOO_SMALL) {
411
			printf("Can't read memory map: %lu\n",
412
			    EFI_ERROR_CODE(status));
413
			goto out;
414
		}
415
416
		free(map);
417
418
		/* Allocate 10 descriptors more than the size reported,
419
		 * to allow for any fragmentation caused by calling
420
		 * malloc */
421
		map = malloc(sz + (10 * dsz));
422
		if (map == NULL) {
423
			printf("Unable to allocate memory\n");
424
			goto out;
425
		}
426
	}
427
428
	safe = true;
429
430
	ndesc = sz / dsz;
431
	for (i = 0, p = map; i < ndesc;
432
	     i++, p = NextMemoryDescriptor(p, dsz)) {
433
		page_start = p->PhysicalStart;
434
		page_end = page_start + p->NumberOfPages * EFI_PAGE_SIZE;
435
436
		overlap_start = page_start > dest ? page_start : dest;
437
		overlap_end = page_end < dest_end ? page_end : dest_end;
438
439
		if (overlap_start < overlap_end &&
440
		    p->Type != EfiLoaderCode &&
441
		    p->Type != EfiLoaderData &&
442
		    p->Type != EfiBootServicesCode &&
443
		    p->Type != EfiBootServicesData &&
444
		    p->Type != EfiConventionalMemory) {
445
			safe = false;
446
			break;
447
		}
448
	}
449
450
out:
451
	free(map);
452
	return safe;
453
}
(-)b/stand/efi/loader/loader_efi.h (-1 / +2 lines)
Lines 44-48 ssize_t efi_readin(readin_handle_t fd, vm_offset_t dest, const size_t len); Link Here
44
void * efi_translate(vm_offset_t ptr);
44
void * efi_translate(vm_offset_t ptr);
45
45
46
void	efi_copy_finish(void);
46
void	efi_copy_finish(void);
47
void efi_copy_get_locations(uint64_t *dst, uint64_t *src, uint64_t *src_end);
48
bool efi_verify_destination_type(void);
47
49
48
#endif	/* _LOADER_EFI_COPY_H_ */
50
#endif	/* _LOADER_EFI_COPY_H_ */
49
- 

Return to bug 209821