Changeset View
Changeset View
Standalone View
Standalone View
stand/efi/loader/arch/amd64/elf64_freebsd.c
Show First 20 Lines • Show All 76 Lines • ▼ Show 20 Lines | struct file_format *file_formats[] = { | ||||||||
&multiboot2_obj, | &multiboot2_obj, | ||||||||
&amd64_elf, | &amd64_elf, | ||||||||
&amd64_elf_obj, | &amd64_elf_obj, | ||||||||
NULL | NULL | ||||||||
}; | }; | ||||||||
static pml4_entry_t *PT4; | static pml4_entry_t *PT4; | ||||||||
static pdp_entry_t *PT3; | static pdp_entry_t *PT3; | ||||||||
static pdp_entry_t *PT3_l, *PT3_u; | |||||||||
static pd_entry_t *PT2; | static pd_entry_t *PT2; | ||||||||
static pd_entry_t *PT2_l0, *PT2_l1, *PT2_l2, *PT2_l3, *PT2_u0, *PT2_u1; | |||||||||
extern EFI_PHYSICAL_ADDRESS staging; | |||||||||
static void (*trampoline)(uint64_t stack, void *copy_finish, uint64_t kernend, | static void (*trampoline)(uint64_t stack, void *copy_finish, uint64_t kernend, | ||||||||
uint64_t modulep, pml4_entry_t *pagetable, uint64_t entry); | uint64_t modulep, pml4_entry_t *pagetable, uint64_t entry); | ||||||||
extern uintptr_t amd64_tramp; | extern uintptr_t amd64_tramp; | ||||||||
extern uint32_t amd64_tramp_size; | extern uint32_t amd64_tramp_size; | ||||||||
/* | /* | ||||||||
* There is an ELF kernel and one or more ELF modules loaded. | * There is an ELF kernel and one or more ELF modules loaded. | ||||||||
* We wish to start executing the kernel image, so make such | * We wish to start executing the kernel image, so make such | ||||||||
* preparations as are required, and do so. | * preparations as are required, and do so. | ||||||||
*/ | */ | ||||||||
static int | static int | ||||||||
elf64_exec(struct preloaded_file *fp) | elf64_exec(struct preloaded_file *fp) | ||||||||
{ | { | ||||||||
struct file_metadata *md; | struct file_metadata *md; | ||||||||
Elf_Ehdr *ehdr; | Elf_Ehdr *ehdr; | ||||||||
vm_offset_t modulep, kernend, trampcode, trampstack; | vm_offset_t modulep, kernend, trampcode, trampstack; | ||||||||
int err, i; | int err, i; | ||||||||
dasebek_gmail.com: "i" would otherwise overflow during virtual page table construction | |||||||||
ACPI_TABLE_RSDP *rsdp; | ACPI_TABLE_RSDP *rsdp; | ||||||||
char buf[24]; | char buf[24]; | ||||||||
int revision; | int revision; | ||||||||
bool copy_auto; | |||||||||
copy_auto = copy_staging == COPY_STAGING_AUTO; | |||||||||
if (copy_auto) | |||||||||
copy_staging = fp->f_kernphys_relocatable ? | |||||||||
COPY_STAGING_DISABLE : COPY_STAGING_ENABLE; | |||||||||
/* | /* | ||||||||
* Report the RSDP to the kernel. While this can be found with | * Report the RSDP to the kernel. While this can be found with | ||||||||
* a BIOS boot, the RSDP may be elsewhere when booted from UEFI. | * a BIOS boot, the RSDP may be elsewhere when booted from UEFI. | ||||||||
* The old code used the 'hints' method to communite this to | * The old code used the 'hints' method to communite this to | ||||||||
* the kernel. However, while convenient, the 'hints' method | * the kernel. However, while convenient, the 'hints' method | ||||||||
* is fragile and does not work when static hints are compiled | * is fragile and does not work when static hints are compiled | ||||||||
* into the kernel. Instead, move to setting different tunables | * into the kernel. Instead, move to setting different tunables | ||||||||
* that start with acpi. The old 'hints' can be removed before | * that start with acpi. The old 'hints' can be removed before | ||||||||
Show All 29 Lines | if (revision >= 2) { | ||||||||
setenv("acpi.xsdt", buf, 1); | setenv("acpi.xsdt", buf, 1); | ||||||||
sprintf(buf, "%d", rsdp->Length); | sprintf(buf, "%d", rsdp->Length); | ||||||||
setenv("hint.acpi.0.xsdt_length", buf, 1); | setenv("hint.acpi.0.xsdt_length", buf, 1); | ||||||||
setenv("acpi.xsdt_length", buf, 1); | setenv("acpi.xsdt_length", buf, 1); | ||||||||
} | } | ||||||||
} | } | ||||||||
if ((md = file_findmetadata(fp, MODINFOMD_ELFHDR)) == NULL) | if ((md = file_findmetadata(fp, MODINFOMD_ELFHDR)) == NULL) | ||||||||
return(EFTYPE); | return (EFTYPE); | ||||||||
ehdr = (Elf_Ehdr *)&(md->md_data); | ehdr = (Elf_Ehdr *)&(md->md_data); | ||||||||
trampcode = (vm_offset_t)0x0000000040000000; | trampcode = copy_staging == COPY_STAGING_ENABLE ? | ||||||||
(vm_offset_t)0x0000000040000000 /* 1G */ : | |||||||||
(vm_offset_t)0x0000000100000000; /* 4G */; | |||||||||
err = BS->AllocatePages(AllocateMaxAddress, EfiLoaderData, 1, | err = BS->AllocatePages(AllocateMaxAddress, EfiLoaderData, 1, | ||||||||
Done Inline ActionsIt would be great if return values like this were not ignored. dasebek_gmail.com: It would be great if return values like this were not ignored. | |||||||||
(EFI_PHYSICAL_ADDRESS *)&trampcode); | (EFI_PHYSICAL_ADDRESS *)&trampcode); | ||||||||
if (EFI_ERROR(err)) { | |||||||||
printf("Unable to allocate trampoline\n"); | |||||||||
if (copy_auto) | |||||||||
copy_staging = COPY_STAGING_AUTO; | |||||||||
return (ENOMEM); | |||||||||
} | |||||||||
bzero((void *)trampcode, EFI_PAGE_SIZE); | bzero((void *)trampcode, EFI_PAGE_SIZE); | ||||||||
trampstack = trampcode + EFI_PAGE_SIZE - 8; | trampstack = trampcode + EFI_PAGE_SIZE - 8; | ||||||||
bcopy((void *)&amd64_tramp, (void *)trampcode, amd64_tramp_size); | bcopy((void *)&amd64_tramp, (void *)trampcode, amd64_tramp_size); | ||||||||
trampoline = (void *)trampcode; | trampoline = (void *)trampcode; | ||||||||
if (copy_staging == COPY_STAGING_ENABLE) { | |||||||||
PT4 = (pml4_entry_t *)0x0000000040000000; | PT4 = (pml4_entry_t *)0x0000000040000000; | ||||||||
err = BS->AllocatePages(AllocateMaxAddress, EfiLoaderData, 3, | err = BS->AllocatePages(AllocateMaxAddress, EfiLoaderData, 3, | ||||||||
(EFI_PHYSICAL_ADDRESS *)&PT4); | (EFI_PHYSICAL_ADDRESS *)&PT4); | ||||||||
if (EFI_ERROR(err)) { | |||||||||
printf("Unable to allocate trampoline page table\n"); | |||||||||
BS->FreePages(trampcode, 1); | |||||||||
if (copy_auto) | |||||||||
copy_staging = COPY_STAGING_AUTO; | |||||||||
return (ENOMEM); | |||||||||
} | |||||||||
bzero(PT4, 3 * EFI_PAGE_SIZE); | bzero(PT4, 3 * EFI_PAGE_SIZE); | ||||||||
PT3 = &PT4[512]; | PT3 = &PT4[512]; | ||||||||
PT2 = &PT3[512]; | PT2 = &PT3[512]; | ||||||||
/* | /* | ||||||||
* This is kinda brutal, but every single 1GB VM memory segment points | * This is kinda brutal, but every single 1GB VM | ||||||||
* to the same first 1GB of physical memory. But it is more than | * memory segment points to the same first 1GB of | ||||||||
* adequate. | * physical memory. But it is more than adequate. | ||||||||
*/ | */ | ||||||||
for (i = 0; i < 512; i++) { | for (i = 0; i < NPTEPG; i++) { | ||||||||
/* Each slot of the L4 pages points to the same L3 page. */ | /* | ||||||||
* Each slot of the L4 pages points to the | |||||||||
* same L3 page. | |||||||||
*/ | |||||||||
PT4[i] = (pml4_entry_t)PT3; | PT4[i] = (pml4_entry_t)PT3; | ||||||||
PT4[i] |= PG_V | PG_RW; | PT4[i] |= PG_V | PG_RW; | ||||||||
/* Each slot of the L3 pages points to the same L2 page. */ | /* | ||||||||
* Each slot of the L3 pages points to the | |||||||||
* same L2 page. | |||||||||
*/ | |||||||||
PT3[i] = (pdp_entry_t)PT2; | PT3[i] = (pdp_entry_t)PT2; | ||||||||
PT3[i] |= PG_V | PG_RW; | PT3[i] |= PG_V | PG_RW; | ||||||||
/* The L2 page slots are mapped with 2MB pages for 1GB. */ | /* | ||||||||
PT2[i] = i * (2 * 1024 * 1024); | * The L2 page slots are mapped with 2MB pages for 1GB. | ||||||||
*/ | |||||||||
PT2[i] = (pd_entry_t)i * (2 * 1024 * 1024); | |||||||||
PT2[i] |= PG_V | PG_RW | PG_PS; | PT2[i] |= PG_V | PG_RW | PG_PS; | ||||||||
} | } | ||||||||
} else { | |||||||||
PT4 = (pml4_entry_t *)0x0000000100000000; /* 4G */ | |||||||||
err = BS->AllocatePages(AllocateMaxAddress, EfiLoaderData, 9, | |||||||||
(EFI_PHYSICAL_ADDRESS *)&PT4); | |||||||||
if (EFI_ERROR(err)) { | |||||||||
printf("Unable to allocate trampoline page table\n"); | |||||||||
BS->FreePages(trampcode, 9); | |||||||||
if (copy_auto) | |||||||||
copy_staging = COPY_STAGING_AUTO; | |||||||||
return (ENOMEM); | |||||||||
} | |||||||||
bzero(PT4, 9 * EFI_PAGE_SIZE); | |||||||||
PT3_l = &PT4[NPML4EPG * 1]; | |||||||||
PT3_u = &PT4[NPML4EPG * 2]; | |||||||||
PT2_l0 = &PT4[NPML4EPG * 3]; | |||||||||
PT2_l1 = &PT4[NPML4EPG * 4]; | |||||||||
PT2_l2 = &PT4[NPML4EPG * 5]; | |||||||||
PT2_l3 = &PT4[NPML4EPG * 6]; | |||||||||
PT2_u0 = &PT4[NPML4EPG * 7]; | |||||||||
PT2_u1 = &PT4[NPML4EPG * 8]; | |||||||||
/* 1:1 mapping of lower 4G */ | |||||||||
PT4[0] = (pml4_entry_t)PT3_l | PG_V | PG_RW; | |||||||||
PT3_l[0] = (pdp_entry_t)PT2_l0 | PG_V | PG_RW; | |||||||||
Done Inline Actionsi was defined as int and could overflow dasebek_gmail.com: i was defined as int and could overflow | |||||||||
Done Inline ActionsIndeed, there was an overflow, but it is not there. i itself cannot overflow, NPTEPG is just 512. kib: Indeed, there was an overflow, but it is not there. i itself cannot overflow, NPTEPG is just… | |||||||||
PT3_l[1] = (pdp_entry_t)PT2_l1 | PG_V | PG_RW; | |||||||||
PT3_l[2] = (pdp_entry_t)PT2_l2 | PG_V | PG_RW; | |||||||||
PT3_l[3] = (pdp_entry_t)PT2_l3 | PG_V | PG_RW; | |||||||||
for (i = 0; i < 4 * NPDEPG; i++) { | |||||||||
PT2_l0[i] = ((pd_entry_t)i << PDRSHIFT) | PG_V | | |||||||||
PG_RW | PG_PS; | |||||||||
} | |||||||||
/* mapping of kernel 2G below top */ | |||||||||
PT4[NPML4EPG - 1] = (pml4_entry_t)PT3_u | PG_V | PG_RW; | |||||||||
PT3_u[NPDPEPG - 2] = (pdp_entry_t)PT2_u0 | PG_V | PG_RW; | |||||||||
PT3_u[NPDPEPG - 1] = (pdp_entry_t)PT2_u1 | PG_V | PG_RW; | |||||||||
/* compat mapping of phys @0 */ | |||||||||
PT2_u0[0] = PG_PS | PG_V | PG_RW; | |||||||||
/* this maps past staging area */ | |||||||||
for (i = 1; i < 2 * NPDEPG; i++) { | |||||||||
Done Inline Actionsi overflowed when defined as int dasebek_gmail.com: i overflowed when defined as int | |||||||||
PT2_u0[i] = ((pd_entry_t)staging + | |||||||||
Done Inline Actions
dasebek_gmail.com: | |||||||||
Done Inline ActionsI explicitly casted i to pd_entry_t, I believe this is the self-explaining way of fixing the issue. kib: I explicitly casted i to pd_entry_t, I believe this is the self-explaining way of fixing the… | |||||||||
((pd_entry_t)i - 1) * NBPDR) | | |||||||||
PG_V | PG_RW | PG_PS; | |||||||||
} | |||||||||
} | |||||||||
printf("staging %#lx (%scoping) tramp %p PT4 %p\n", | |||||||||
staging, copy_staging == COPY_STAGING_ENABLE ? "" : "not ", | |||||||||
trampoline, PT4); | |||||||||
printf("Start @ 0x%lx ...\n", ehdr->e_entry); | printf("Start @ 0x%lx ...\n", ehdr->e_entry); | ||||||||
efi_time_fini(); | efi_time_fini(); | ||||||||
err = bi_load(fp->f_args, &modulep, &kernend, true); | err = bi_load(fp->f_args, &modulep, &kernend, true); | ||||||||
if (err != 0) { | if (err != 0) { | ||||||||
efi_time_init(); | efi_time_init(); | ||||||||
if (copy_auto) | |||||||||
copy_staging = COPY_STAGING_AUTO; | |||||||||
return(err); | return (err); | ||||||||
} | } | ||||||||
dev_cleanup(); | dev_cleanup(); | ||||||||
trampoline(trampstack, efi_copy_finish, kernend, modulep, PT4, | trampoline(trampstack, copy_staging == COPY_STAGING_ENABLE ? | ||||||||
ehdr->e_entry); | efi_copy_finish : efi_copy_finish_nop, kernend, modulep, | ||||||||
PT4, ehdr->e_entry); | |||||||||
panic("exec returned"); | panic("exec returned"); | ||||||||
} | } | ||||||||
Done Inline ActionsIndentation is off. markj: Indentation is off. | |||||||||
static int | static int | ||||||||
elf64_obj_exec(struct preloaded_file *fp) | elf64_obj_exec(struct preloaded_file *fp) | ||||||||
{ | { | ||||||||
return (EFTYPE); | return (EFTYPE); | ||||||||
} | } |
"i" would otherwise overflow during virtual page table construction