xref: /freebsd/stand/common/metadata.c (revision 3e15b01d)
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
md_getboothowto(char * kargs)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
md_load_dual(char * args,vm_offset_t * modulep,vm_offset_t * dtb,int kern64)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;
149d3e1307bSJustin Hibbits     kfp = file_findfile(NULL, kern64 ? "elf64 kernel" : "elf32 kernel");
150d3e1307bSJustin Hibbits     if (kfp == NULL)
151d3e1307bSJustin Hibbits 	kfp = file_findfile(NULL, "elf kernel");
152d3e1307bSJustin Hibbits     if (kfp == NULL)
153d3e1307bSJustin Hibbits 	panic("can't find kernel file");
154d3e1307bSJustin Hibbits     file_addmetadata(kfp, MODINFOMD_HOWTO, sizeof howto, &howto);
155d3e1307bSJustin Hibbits     if (kern64) {
156d3e1307bSJustin Hibbits 	scratch64 = envp;
157d3e1307bSJustin Hibbits 	file_addmetadata(kfp, MODINFOMD_ENVP, sizeof scratch64, &scratch64);
158d3e1307bSJustin Hibbits #if defined(LOADER_FDT_SUPPORT)
159d3e1307bSJustin Hibbits 	if (fdtp != 0) {
160d3e1307bSJustin Hibbits 	    scratch64 = fdtp;
161d3e1307bSJustin Hibbits 	    file_addmetadata(kfp, MODINFOMD_DTBP, sizeof scratch64, &scratch64);
162d3e1307bSJustin Hibbits 	}
163d3e1307bSJustin Hibbits #endif
164d3e1307bSJustin Hibbits 	scratch64 = kernend;
165d3e1307bSJustin Hibbits 	file_addmetadata(kfp, MODINFOMD_KERNEND,
166d3e1307bSJustin Hibbits 		sizeof scratch64, &scratch64);
167d3e1307bSJustin Hibbits     } else {
168d3e1307bSJustin Hibbits 	file_addmetadata(kfp, MODINFOMD_ENVP, sizeof envp, &envp);
169d3e1307bSJustin Hibbits #if defined(LOADER_FDT_SUPPORT)
170d3e1307bSJustin Hibbits 	if (fdtp != 0)
171d3e1307bSJustin Hibbits 	    file_addmetadata(kfp, MODINFOMD_DTBP, sizeof fdtp, &fdtp);
172d3e1307bSJustin Hibbits #endif
173d3e1307bSJustin Hibbits 	file_addmetadata(kfp, MODINFOMD_KERNEND, sizeof kernend, &kernend);
174d3e1307bSJustin Hibbits     }
175c1418270SIan Lepore #ifdef LOADER_GELI_SUPPORT
176c1418270SIan Lepore     geli_export_key_metadata(kfp);
177c1418270SIan Lepore #endif
178d3e1307bSJustin Hibbits 
179d3e1307bSJustin Hibbits     *modulep = addr;
180d3e1307bSJustin Hibbits     size = md_copymodules(0, kern64);
181d3e1307bSJustin Hibbits     kernend = roundup(addr + size, PAGE_SIZE);
182d3e1307bSJustin Hibbits 
183d3e1307bSJustin Hibbits     md = file_findmetadata(kfp, MODINFOMD_KERNEND);
184d3e1307bSJustin Hibbits     if (kern64) {
185d3e1307bSJustin Hibbits 	scratch64 = kernend;
186d3e1307bSJustin Hibbits 	bcopy(&scratch64, md->md_data, sizeof scratch64);
187d3e1307bSJustin Hibbits     } else {
188d3e1307bSJustin Hibbits 	bcopy(&kernend, md->md_data, sizeof kernend);
189d3e1307bSJustin Hibbits     }
190d3e1307bSJustin Hibbits 
1914daa199dSKyle Evans #ifdef __arm__
1924daa199dSKyle Evans     /* Convert addresses to the final VA */
1934daa199dSKyle Evans     *modulep -= __elfN(relocation_offset);
1944daa199dSKyle Evans 
1954daa199dSKyle Evans     /* Do relocation fixup on metadata of each module. */
1964daa199dSKyle Evans     for (xp = file_findfile(NULL, NULL); xp != NULL; xp = xp->f_next) {
1974daa199dSKyle Evans         for (i = 0; i < nitems(mdt); i++) {
1984daa199dSKyle Evans             md = file_findmetadata(xp, mdt[i]);
1994daa199dSKyle Evans                 if (md) {
2004daa199dSKyle Evans                     bcopy(md->md_data, &vaddr, sizeof vaddr);
2014daa199dSKyle Evans                     vaddr -= __elfN(relocation_offset);
2024daa199dSKyle Evans                     bcopy(&vaddr, md->md_data, sizeof vaddr);
2034daa199dSKyle Evans                 }
2044daa199dSKyle Evans             }
2054daa199dSKyle Evans     }
2064daa199dSKyle Evans #endif
2074daa199dSKyle Evans 
208d3e1307bSJustin Hibbits     (void)md_copymodules(addr, kern64);
209d3e1307bSJustin Hibbits #if defined(LOADER_FDT_SUPPORT)
210d3e1307bSJustin Hibbits     if (dtb != NULL)
211d3e1307bSJustin Hibbits 	*dtb = fdtp;
212d3e1307bSJustin Hibbits #endif
213d3e1307bSJustin Hibbits 
214d3e1307bSJustin Hibbits     return(0);
215d3e1307bSJustin Hibbits }
216d3e1307bSJustin Hibbits 
217d3e1307bSJustin Hibbits int
md_load(char * args,vm_offset_t * modulep,vm_offset_t * dtb)218d3e1307bSJustin Hibbits md_load(char *args, vm_offset_t *modulep, vm_offset_t *dtb)
219d3e1307bSJustin Hibbits {
220d3e1307bSJustin Hibbits     return (md_load_dual(args, modulep, dtb, 0));
221d3e1307bSJustin Hibbits }
222d3e1307bSJustin Hibbits 
22320b23ae7SWarner Losh #if defined(__powerpc__)
224d3e1307bSJustin Hibbits int
md_load64(char * args,vm_offset_t * modulep,vm_offset_t * dtb)225d3e1307bSJustin Hibbits md_load64(char *args, vm_offset_t *modulep, vm_offset_t *dtb)
226d3e1307bSJustin Hibbits {
227d3e1307bSJustin Hibbits     return (md_load_dual(args, modulep, dtb, 1));
228d3e1307bSJustin Hibbits }
229d3e1307bSJustin Hibbits #endif
230