1d3e1307bSJustin Hibbits /*- 2d3e1307bSJustin Hibbits * Copyright (c) 1998 Michael Smith <msmith@freebsd.org> 3d3e1307bSJustin Hibbits * All rights reserved. 4d3e1307bSJustin Hibbits * 5d3e1307bSJustin Hibbits * Redistribution and use in source and binary forms, with or without 6d3e1307bSJustin Hibbits * modification, are permitted provided that the following conditions 7d3e1307bSJustin Hibbits * are met: 8d3e1307bSJustin Hibbits * 1. Redistributions of source code must retain the above copyright 9d3e1307bSJustin Hibbits * notice, this list of conditions and the following disclaimer. 10d3e1307bSJustin Hibbits * 2. Redistributions in binary form must reproduce the above copyright 11d3e1307bSJustin Hibbits * notice, this list of conditions and the following disclaimer in the 12d3e1307bSJustin Hibbits * documentation and/or other materials provided with the distribution. 13d3e1307bSJustin Hibbits * 14d3e1307bSJustin Hibbits * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15d3e1307bSJustin Hibbits * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16d3e1307bSJustin Hibbits * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17d3e1307bSJustin Hibbits * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18d3e1307bSJustin Hibbits * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19d3e1307bSJustin Hibbits * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20d3e1307bSJustin Hibbits * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21d3e1307bSJustin Hibbits * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22d3e1307bSJustin Hibbits * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23d3e1307bSJustin Hibbits * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24d3e1307bSJustin Hibbits * SUCH DAMAGE. 25d3e1307bSJustin Hibbits * 26d3e1307bSJustin Hibbits * from: FreeBSD: src/sys/boot/sparc64/loader/metadata.c,v 1.6 27d3e1307bSJustin Hibbits */ 28d3e1307bSJustin Hibbits 29d3e1307bSJustin Hibbits #include <stand.h> 30d3e1307bSJustin Hibbits #include <sys/param.h> 31d3e1307bSJustin Hibbits #include <sys/linker.h> 324569e913SWarner Losh #include <sys/boot.h> 3328ee318dSKyle Evans #include <sys/reboot.h> 34d3e1307bSJustin Hibbits #if defined(LOADER_FDT_SUPPORT) 35d3e1307bSJustin Hibbits #include <fdt_platform.h> 36d3e1307bSJustin Hibbits #endif 37d3e1307bSJustin Hibbits 384daa199dSKyle Evans #ifdef __arm__ 394daa199dSKyle Evans #include <machine/elf.h> 404daa199dSKyle Evans #endif 41d3e1307bSJustin Hibbits #include <machine/metadata.h> 42d3e1307bSJustin Hibbits 43d3e1307bSJustin Hibbits #include "bootstrap.h" 44bca9c87bSWarner Losh #include "modinfo.h" 45d3e1307bSJustin Hibbits 46c1418270SIan Lepore #ifdef LOADER_GELI_SUPPORT 47c1418270SIan Lepore #include "geliboot.h" 48c1418270SIan Lepore #endif 49c1418270SIan Lepore 50dd5dbb31SMarius Strobl static int 51d3e1307bSJustin Hibbits md_getboothowto(char *kargs) 52d3e1307bSJustin Hibbits { 53d3e1307bSJustin Hibbits int howto; 54d3e1307bSJustin Hibbits 55d3e1307bSJustin Hibbits /* Parse kargs */ 564569e913SWarner Losh howto = boot_parse_cmdline(kargs); 57c96ac12eSWarner Losh howto |= boot_env_to_howto(); 58d3e1307bSJustin Hibbits if (!strcmp(getenv("console"), "comconsole")) 59d3e1307bSJustin Hibbits howto |= RB_SERIAL; 60d3e1307bSJustin Hibbits if (!strcmp(getenv("console"), "nullconsole")) 61d3e1307bSJustin Hibbits howto |= RB_MUTE; 62d3e1307bSJustin Hibbits return(howto); 63d3e1307bSJustin Hibbits } 64d3e1307bSJustin Hibbits 65d3e1307bSJustin Hibbits /* 66d3e1307bSJustin Hibbits * Load the information expected by a kernel. 67d3e1307bSJustin Hibbits * 68d3e1307bSJustin Hibbits * - The 'boothowto' argument is constructed 69d3e1307bSJustin Hibbits * - The 'bootdev' argument is constructed 70d3e1307bSJustin Hibbits * - The kernel environment is copied into kernel space. 71d3e1307bSJustin Hibbits * - Module metadata are formatted and placed in kernel space. 72d3e1307bSJustin Hibbits */ 73dd5dbb31SMarius Strobl static int 74d3e1307bSJustin Hibbits md_load_dual(char *args, vm_offset_t *modulep, vm_offset_t *dtb, int kern64) 75d3e1307bSJustin Hibbits { 76d3e1307bSJustin Hibbits struct preloaded_file *kfp; 77d3e1307bSJustin Hibbits struct preloaded_file *xp; 78d3e1307bSJustin Hibbits struct file_metadata *md; 79d3e1307bSJustin Hibbits vm_offset_t kernend; 80d3e1307bSJustin Hibbits vm_offset_t addr; 81d3e1307bSJustin Hibbits vm_offset_t envp; 82d3e1307bSJustin Hibbits #if defined(LOADER_FDT_SUPPORT) 83d3e1307bSJustin Hibbits vm_offset_t fdtp; 84d3e1307bSJustin Hibbits #endif 85d3e1307bSJustin Hibbits vm_offset_t size; 86d3e1307bSJustin Hibbits uint64_t scratch64; 87d3e1307bSJustin Hibbits char *rootdevname; 88d3e1307bSJustin Hibbits int howto; 894daa199dSKyle Evans #ifdef __arm__ 904daa199dSKyle Evans vm_offset_t vaddr; 914daa199dSKyle Evans int i; 924daa199dSKyle Evans 934daa199dSKyle Evans /* 944daa199dSKyle Evans * These metadata addreses must be converted for kernel after 954daa199dSKyle Evans * relocation. 964daa199dSKyle Evans */ 974daa199dSKyle Evans uint32_t mdt[] = { 984daa199dSKyle Evans MODINFOMD_SSYM, MODINFOMD_ESYM, MODINFOMD_KERNEND, 994daa199dSKyle Evans MODINFOMD_ENVP, 1004daa199dSKyle Evans #if defined(LOADER_FDT_SUPPORT) 1014daa199dSKyle Evans MODINFOMD_DTBP 1024daa199dSKyle Evans #endif 1034daa199dSKyle Evans }; 1044daa199dSKyle Evans #endif 105d3e1307bSJustin Hibbits 106d3e1307bSJustin Hibbits howto = md_getboothowto(args); 107d3e1307bSJustin Hibbits 108d3e1307bSJustin Hibbits /* 109d3e1307bSJustin Hibbits * Allow the environment variable 'rootdev' to override the supplied 110d3e1307bSJustin Hibbits * device. This should perhaps go to MI code and/or have $rootdev 111d3e1307bSJustin Hibbits * tested/set by MI code before launching the kernel. 112d3e1307bSJustin Hibbits */ 113d3e1307bSJustin Hibbits rootdevname = getenv("rootdev"); 114d3e1307bSJustin Hibbits if (rootdevname == NULL) 115d3e1307bSJustin Hibbits rootdevname = getenv("currdev"); 116d3e1307bSJustin Hibbits /* Try reading the /etc/fstab file to select the root device */ 117d3e1307bSJustin Hibbits getrootmount(rootdevname); 118d3e1307bSJustin Hibbits 119d3e1307bSJustin Hibbits /* Find the last module in the chain */ 120d3e1307bSJustin Hibbits addr = 0; 121d3e1307bSJustin Hibbits for (xp = file_findfile(NULL, NULL); xp != NULL; xp = xp->f_next) { 122d3e1307bSJustin Hibbits if (addr < (xp->f_addr + xp->f_size)) 123d3e1307bSJustin Hibbits addr = xp->f_addr + xp->f_size; 124d3e1307bSJustin Hibbits } 125d3e1307bSJustin Hibbits /* Pad to a page boundary */ 126d3e1307bSJustin Hibbits addr = roundup(addr, PAGE_SIZE); 127d3e1307bSJustin Hibbits 128d3e1307bSJustin Hibbits /* Copy our environment */ 129d3e1307bSJustin Hibbits envp = addr; 130d3e1307bSJustin Hibbits addr = md_copyenv(addr); 131d3e1307bSJustin Hibbits 132d3e1307bSJustin Hibbits /* Pad to a page boundary */ 133d3e1307bSJustin Hibbits addr = roundup(addr, PAGE_SIZE); 134d3e1307bSJustin Hibbits 135d3e1307bSJustin Hibbits #if defined(LOADER_FDT_SUPPORT) 136d3e1307bSJustin Hibbits /* Copy out FDT */ 137d3e1307bSJustin Hibbits fdtp = 0; 138d3e1307bSJustin Hibbits #if defined(__powerpc__) 139d3e1307bSJustin Hibbits if (getenv("usefdt") != NULL) 140d3e1307bSJustin Hibbits #endif 141d3e1307bSJustin Hibbits { 142d3e1307bSJustin Hibbits size = fdt_copy(addr); 143d3e1307bSJustin Hibbits fdtp = addr; 144d3e1307bSJustin Hibbits addr = roundup(addr + size, PAGE_SIZE); 145d3e1307bSJustin Hibbits } 146d3e1307bSJustin Hibbits #endif 147d3e1307bSJustin Hibbits 148d3e1307bSJustin Hibbits kernend = 0; 149*86077f4fSAhmad Khalifa kfp = file_findfile(NULL, md_kerntype); 150d3e1307bSJustin Hibbits if (kfp == NULL) 151d3e1307bSJustin Hibbits panic("can't find kernel file"); 152d3e1307bSJustin Hibbits file_addmetadata(kfp, MODINFOMD_HOWTO, sizeof howto, &howto); 153d3e1307bSJustin Hibbits if (kern64) { 154d3e1307bSJustin Hibbits scratch64 = envp; 155d3e1307bSJustin Hibbits file_addmetadata(kfp, MODINFOMD_ENVP, sizeof scratch64, &scratch64); 156d3e1307bSJustin Hibbits #if defined(LOADER_FDT_SUPPORT) 157d3e1307bSJustin Hibbits if (fdtp != 0) { 158d3e1307bSJustin Hibbits scratch64 = fdtp; 159d3e1307bSJustin Hibbits file_addmetadata(kfp, MODINFOMD_DTBP, sizeof scratch64, &scratch64); 160d3e1307bSJustin Hibbits } 161d3e1307bSJustin Hibbits #endif 162d3e1307bSJustin Hibbits scratch64 = kernend; 163d3e1307bSJustin Hibbits file_addmetadata(kfp, MODINFOMD_KERNEND, 164d3e1307bSJustin Hibbits sizeof scratch64, &scratch64); 165d3e1307bSJustin Hibbits } else { 166d3e1307bSJustin Hibbits file_addmetadata(kfp, MODINFOMD_ENVP, sizeof envp, &envp); 167d3e1307bSJustin Hibbits #if defined(LOADER_FDT_SUPPORT) 168d3e1307bSJustin Hibbits if (fdtp != 0) 169d3e1307bSJustin Hibbits file_addmetadata(kfp, MODINFOMD_DTBP, sizeof fdtp, &fdtp); 170d3e1307bSJustin Hibbits #endif 171d3e1307bSJustin Hibbits file_addmetadata(kfp, MODINFOMD_KERNEND, sizeof kernend, &kernend); 172d3e1307bSJustin Hibbits } 173c1418270SIan Lepore #ifdef LOADER_GELI_SUPPORT 174c1418270SIan Lepore geli_export_key_metadata(kfp); 175c1418270SIan Lepore #endif 176d3e1307bSJustin Hibbits 177d3e1307bSJustin Hibbits *modulep = addr; 178d3e1307bSJustin Hibbits size = md_copymodules(0, kern64); 179d3e1307bSJustin Hibbits kernend = roundup(addr + size, PAGE_SIZE); 180d3e1307bSJustin Hibbits 181d3e1307bSJustin Hibbits md = file_findmetadata(kfp, MODINFOMD_KERNEND); 182d3e1307bSJustin Hibbits if (kern64) { 183d3e1307bSJustin Hibbits scratch64 = kernend; 184d3e1307bSJustin Hibbits bcopy(&scratch64, md->md_data, sizeof scratch64); 185d3e1307bSJustin Hibbits } else { 186d3e1307bSJustin Hibbits bcopy(&kernend, md->md_data, sizeof kernend); 187d3e1307bSJustin Hibbits } 188d3e1307bSJustin Hibbits 1894daa199dSKyle Evans #ifdef __arm__ 1904daa199dSKyle Evans /* Convert addresses to the final VA */ 1914daa199dSKyle Evans *modulep -= __elfN(relocation_offset); 1924daa199dSKyle Evans 1934daa199dSKyle Evans /* Do relocation fixup on metadata of each module. */ 1944daa199dSKyle Evans for (xp = file_findfile(NULL, NULL); xp != NULL; xp = xp->f_next) { 1954daa199dSKyle Evans for (i = 0; i < nitems(mdt); i++) { 1964daa199dSKyle Evans md = file_findmetadata(xp, mdt[i]); 1974daa199dSKyle Evans if (md) { 1984daa199dSKyle Evans bcopy(md->md_data, &vaddr, sizeof vaddr); 1994daa199dSKyle Evans vaddr -= __elfN(relocation_offset); 2004daa199dSKyle Evans bcopy(&vaddr, md->md_data, sizeof vaddr); 2014daa199dSKyle Evans } 2024daa199dSKyle Evans } 2034daa199dSKyle Evans } 2044daa199dSKyle Evans #endif 2054daa199dSKyle Evans 206d3e1307bSJustin Hibbits (void)md_copymodules(addr, kern64); 207d3e1307bSJustin Hibbits #if defined(LOADER_FDT_SUPPORT) 208d3e1307bSJustin Hibbits if (dtb != NULL) 209d3e1307bSJustin Hibbits *dtb = fdtp; 210d3e1307bSJustin Hibbits #endif 211d3e1307bSJustin Hibbits 212d3e1307bSJustin Hibbits return(0); 213d3e1307bSJustin Hibbits } 214d3e1307bSJustin Hibbits 215d3e1307bSJustin Hibbits int 216d3e1307bSJustin Hibbits md_load(char *args, vm_offset_t *modulep, vm_offset_t *dtb) 217d3e1307bSJustin Hibbits { 218d3e1307bSJustin Hibbits return (md_load_dual(args, modulep, dtb, 0)); 219d3e1307bSJustin Hibbits } 220d3e1307bSJustin Hibbits 22120b23ae7SWarner Losh #if defined(__powerpc__) 222d3e1307bSJustin Hibbits int 223d3e1307bSJustin Hibbits md_load64(char *args, vm_offset_t *modulep, vm_offset_t *dtb) 224d3e1307bSJustin Hibbits { 225d3e1307bSJustin Hibbits return (md_load_dual(args, modulep, dtb, 1)); 226d3e1307bSJustin Hibbits } 227d3e1307bSJustin Hibbits #endif 228