| Commit | Line | Data |
|---|---|---|
| 984263bc MD |
1 | /*- |
| 2 | * Copyright (c) 1998 Michael Smith <msmith@freebsd.org> | |
| 3 | * All rights reserved. | |
| 4 | * | |
| 5 | * Redistribution and use in source and binary forms, with or without | |
| 6 | * modification, are permitted provided that the following conditions | |
| 7 | * are met: | |
| 8 | * 1. Redistributions of source code must retain the above copyright | |
| 9 | * notice, this list of conditions and the following disclaimer. | |
| 10 | * 2. Redistributions in binary form must reproduce the above copyright | |
| 11 | * notice, this list of conditions and the following disclaimer in the | |
| 12 | * documentation and/or other materials provided with the distribution. | |
| 13 | * | |
| 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | |
| 15 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
| 16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
| 17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | |
| 18 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
| 19 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
| 20 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
| 21 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
| 22 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
| 23 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
| 24 | * SUCH DAMAGE. | |
| 25 | * | |
| 5ee58eed | 26 | * $FreeBSD: src/sys/boot/i386/libi386/elf64_freebsd.c,v 1.14 2003/08/25 23:28:31 obrien Exp $ |
| 44447690 | 27 | * $DragonFly: src/sys/boot/pc32/libi386/elf64_freebsd.c,v 1.3 2008/08/25 16:58:41 dillon Exp $ |
| 984263bc MD |
28 | */ |
| 29 | ||
| 5ee58eed | 30 | #define __ELF_WORD_SIZE 64 |
| 984263bc MD |
31 | #include <sys/param.h> |
| 32 | #include <sys/exec.h> | |
| 984263bc MD |
33 | #include <sys/linker.h> |
| 34 | #include <string.h> | |
| 35 | #include <machine/bootinfo.h> | |
| 36 | #include <machine/elf.h> | |
| 37 | #include <stand.h> | |
| 38 | ||
| 39 | #include "bootstrap.h" | |
| 40 | #include "libi386.h" | |
| 41 | #include "btxv86.h" | |
| 42 | ||
| 5ee58eed | 43 | static int elf64_exec(struct preloaded_file *amp); |
| 6f3c5d3d | 44 | static int elf64_obj_exec(struct preloaded_file *amp); |
| 984263bc | 45 | |
| c1543a89 SS |
46 | struct file_format x86_64_elf = { elf64_loadfile, elf64_exec }; |
| 47 | struct file_format x86_64_elf_obj = { elf64_obj_loadfile, elf64_obj_exec }; | |
| 5ee58eed MD |
48 | |
| 49 | #define PG_V 0x001 | |
| 50 | #define PG_RW 0x002 | |
| 51 | #define PG_U 0x004 | |
| 52 | #define PG_PS 0x080 | |
| 53 | ||
| 54 | typedef u_int64_t p4_entry_t; | |
| 55 | typedef u_int64_t p3_entry_t; | |
| 56 | typedef u_int64_t p2_entry_t; | |
| 57 | extern p4_entry_t PT4[]; | |
| 58 | extern p3_entry_t PT3[]; | |
| 59 | extern p2_entry_t PT2[]; | |
| 60 | ||
| 61 | u_int32_t entry_hi; | |
| 62 | u_int32_t entry_lo; | |
| 63 | ||
| c1543a89 | 64 | extern int x86_64_tramp(void); |
| 984263bc MD |
65 | |
| 66 | /* | |
| 6f3c5d3d | 67 | * There is an ELF kernel and one or more ELF modules loaded. |
| 984263bc MD |
68 | * We wish to start executing the kernel image, so make such |
| 69 | * preparations as are required, and do so. | |
| 70 | */ | |
| 71 | static int | |
| 5ee58eed | 72 | elf64_exec(struct preloaded_file *fp) |
| 984263bc | 73 | { |
| 5ee58eed | 74 | struct file_metadata *md; |
| 984263bc | 75 | Elf_Ehdr *ehdr; |
| 5ee58eed MD |
76 | vm_offset_t modulep, kernend; |
| 77 | int err; | |
| 78 | int i; | |
| 984263bc | 79 | |
| 5ee58eed | 80 | if ((md = file_findmetadata(fp, MODINFOMD_ELFHDR)) == NULL) |
| 984263bc MD |
81 | return(EFTYPE); /* XXX actually EFUCKUP */ |
| 82 | ehdr = (Elf_Ehdr *)&(md->md_data); | |
| 83 | ||
| 5ee58eed MD |
84 | err = bi_load64(fp->f_args, &modulep, &kernend); |
| 85 | if (err != 0) | |
| 984263bc | 86 | return(err); |
| 984263bc | 87 | |
| 5ee58eed MD |
88 | bzero(PT4, PAGE_SIZE); |
| 89 | bzero(PT3, PAGE_SIZE); | |
| 90 | bzero(PT2, PAGE_SIZE); | |
| 91 | ||
| 92 | /* | |
| 6f3c5d3d SS |
93 | * This is kinda brutal, but every single 1GB VM memory segment points to |
| 94 | * the same first 1GB of physical memory. But it is more than adequate. | |
| 5ee58eed MD |
95 | */ |
| 96 | for (i = 0; i < 512; i++) { | |
| 97 | /* Each slot of the level 4 pages points to the same level 3 page */ | |
| 98 | PT4[i] = (p4_entry_t)VTOP((uintptr_t)&PT3[0]); | |
| 99 | PT4[i] |= PG_V | PG_RW | PG_U; | |
| 100 | ||
| 101 | /* Each slot of the level 3 pages points to the same level 2 page */ | |
| 102 | PT3[i] = (p3_entry_t)VTOP((uintptr_t)&PT2[0]); | |
| 103 | PT3[i] |= PG_V | PG_RW | PG_U; | |
| 6f3c5d3d | 104 | |
| 5ee58eed MD |
105 | /* The level 2 page slots are mapped with 2MB pages for 1GB. */ |
| 106 | PT2[i] = i * (2 * 1024 * 1024); | |
| 107 | PT2[i] |= PG_V | PG_RW | PG_PS | PG_U; | |
| 108 | } | |
| 984263bc | 109 | |
| 5ee58eed MD |
110 | entry_lo = ehdr->e_entry & 0xffffffff; |
| 111 | entry_hi = (ehdr->e_entry >> 32) & 0xffffffff; | |
| 984263bc | 112 | #ifdef DEBUG |
| 5ee58eed | 113 | printf("Start @ %#llx ...\n", ehdr->e_entry); |
| 984263bc MD |
114 | #endif |
| 115 | ||
| 116 | dev_cleanup(); | |
| c1543a89 | 117 | __exec((void *)VTOP(x86_64_tramp), modulep, kernend); |
| 984263bc MD |
118 | |
| 119 | panic("exec returned"); | |
| 120 | } | |
| 6f3c5d3d SS |
121 | |
| 122 | static int | |
| 123 | elf64_obj_exec(struct preloaded_file *fp) | |
| 124 | { | |
| 125 | return (EFTYPE); | |
| 126 | } |