xref: /freebsd/sys/powerpc/ofw/ofw_initrd.c (revision fdafd315ad0d0f28a11b9fb4476a9ab059c62b92)
13ddc2cdeSBreno Leitao /*-
23ddc2cdeSBreno Leitao  * Copyright (C) 2018 Breno Leitao
33ddc2cdeSBreno Leitao  *
43ddc2cdeSBreno Leitao  * Redistribution and use in source and binary forms, with or without
53ddc2cdeSBreno Leitao  * modification, are permitted provided that the following conditions
63ddc2cdeSBreno Leitao  * are met:
73ddc2cdeSBreno Leitao  * 1. Redistributions of source code must retain the above copyright
83ddc2cdeSBreno Leitao  *    notice, this list of conditions and the following disclaimer.
93ddc2cdeSBreno Leitao  * 2. Redistributions in binary form must reproduce the above copyright
103ddc2cdeSBreno Leitao  *    notice, this list of conditions and the following disclaimer in the
113ddc2cdeSBreno Leitao  *    documentation and/or other materials provided with the distribution.
123ddc2cdeSBreno Leitao  *
133ddc2cdeSBreno Leitao  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
143ddc2cdeSBreno Leitao  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
153ddc2cdeSBreno Leitao  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
163ddc2cdeSBreno Leitao  * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
173ddc2cdeSBreno Leitao  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
183ddc2cdeSBreno Leitao  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
193ddc2cdeSBreno Leitao  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
203ddc2cdeSBreno Leitao  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
213ddc2cdeSBreno Leitao  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
223ddc2cdeSBreno Leitao  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
233ddc2cdeSBreno Leitao  */
243ddc2cdeSBreno Leitao 
253ddc2cdeSBreno Leitao #include <sys/param.h>
263ddc2cdeSBreno Leitao #include <sys/kernel.h>
273ddc2cdeSBreno Leitao #include <sys/systm.h>
283ddc2cdeSBreno Leitao #include <sys/module.h>
293ddc2cdeSBreno Leitao #include <sys/types.h>
303ddc2cdeSBreno Leitao #include <sys/proc.h>
313ddc2cdeSBreno Leitao 
323ddc2cdeSBreno Leitao #include <vm/vm.h>
333ddc2cdeSBreno Leitao #include <vm/pmap.h>
343ddc2cdeSBreno Leitao 
353ddc2cdeSBreno Leitao #include <machine/bus.h>
36*9411e24dSBrandon Bergren #include <machine/elf.h>
37*9411e24dSBrandon Bergren #include <machine/param.h>
383ddc2cdeSBreno Leitao 
393ddc2cdeSBreno Leitao #include <dev/ofw/openfirm.h>
403ddc2cdeSBreno Leitao #include <dev/ofw/ofw_bus.h>
413ddc2cdeSBreno Leitao #include <dev/ofw/ofw_bus_subr.h>
423ddc2cdeSBreno Leitao 
433ddc2cdeSBreno Leitao #include "opt_md.h"
443ddc2cdeSBreno Leitao 
453ddc2cdeSBreno Leitao extern u_char *mfs_root;
465d8c3a06SLeandro Lupori extern int mfs_root_size;
473ddc2cdeSBreno Leitao 
485d8c3a06SLeandro Lupori static void ofw_initrd_probe_and_attach(void *junk);
493ddc2cdeSBreno Leitao 
505d8c3a06SLeandro Lupori SYSINIT(ofw_initrd_probe_and_attach, SI_SUB_KMEM, SI_ORDER_ANY,
515d8c3a06SLeandro Lupori     ofw_initrd_probe_and_attach, NULL);
523ddc2cdeSBreno Leitao 
535d8c3a06SLeandro Lupori static void
ofw_initrd_probe_and_attach(void * junk)545d8c3a06SLeandro Lupori ofw_initrd_probe_and_attach(void *junk)
553ddc2cdeSBreno Leitao {
563ddc2cdeSBreno Leitao 	phandle_t chosen;
573ddc2cdeSBreno Leitao 	vm_paddr_t start, end;
583ddc2cdeSBreno Leitao 	pcell_t cell[2];
593ddc2cdeSBreno Leitao 	ssize_t size;
60*9411e24dSBrandon Bergren 	u_char *taste;
61*9411e24dSBrandon Bergren 	Elf_Ehdr ehdr;
623ddc2cdeSBreno Leitao 
635d8c3a06SLeandro Lupori 	if (!hw_direct_map)
645d8c3a06SLeandro Lupori 		return;
653ddc2cdeSBreno Leitao 
663ddc2cdeSBreno Leitao 	chosen = OF_finddevice("/chosen");
675d8c3a06SLeandro Lupori 	if (chosen <= 0)
685d8c3a06SLeandro Lupori 		return;
695d8c3a06SLeandro Lupori 
705d8c3a06SLeandro Lupori 	if (!OF_hasprop(chosen, "linux,initrd-start") ||
715d8c3a06SLeandro Lupori 	    !OF_hasprop(chosen, "linux,initrd-end"))
725d8c3a06SLeandro Lupori 		return;
733ddc2cdeSBreno Leitao 
743ddc2cdeSBreno Leitao 	size = OF_getencprop(chosen, "linux,initrd-start", cell, sizeof(cell));
753ddc2cdeSBreno Leitao 	if (size == 4)
763ddc2cdeSBreno Leitao 		start = cell[0];
773ddc2cdeSBreno Leitao 	else if (size == 8)
783ddc2cdeSBreno Leitao 		start = (uint64_t)cell[0] << 32 | cell[1];
793ddc2cdeSBreno Leitao 	else {
805d8c3a06SLeandro Lupori 		printf("ofw_initrd: Wrong linux,initrd-start size\n");
815d8c3a06SLeandro Lupori 		return;
823ddc2cdeSBreno Leitao 	}
833ddc2cdeSBreno Leitao 
843ddc2cdeSBreno Leitao 	size = OF_getencprop(chosen, "linux,initrd-end", cell, sizeof(cell));
853ddc2cdeSBreno Leitao 	if (size == 4)
863ddc2cdeSBreno Leitao 		end = cell[0];
873ddc2cdeSBreno Leitao 	else if (size == 8)
883ddc2cdeSBreno Leitao 		end = (uint64_t)cell[0] << 32 | cell[1];
893ddc2cdeSBreno Leitao 	else{
905d8c3a06SLeandro Lupori 		printf("ofw_initrd: Wrong linux,initrd-end size\n");
915d8c3a06SLeandro Lupori 		return;
923ddc2cdeSBreno Leitao 	}
933ddc2cdeSBreno Leitao 
943ddc2cdeSBreno Leitao 	if (end - start > 0) {
95*9411e24dSBrandon Bergren 		taste = (u_char*) PHYS_TO_DMAP(start);
96*9411e24dSBrandon Bergren 		memcpy(&ehdr, taste, sizeof(ehdr));
97*9411e24dSBrandon Bergren 
98*9411e24dSBrandon Bergren 		if (IS_ELF(ehdr)) {
99*9411e24dSBrandon Bergren 			printf("ofw_initrd: initrd is kernel image!\n");
100*9411e24dSBrandon Bergren 			return;
101*9411e24dSBrandon Bergren 		}
102*9411e24dSBrandon Bergren 
103*9411e24dSBrandon Bergren 		mfs_root = taste;
1043ddc2cdeSBreno Leitao 		mfs_root_size = end - start;
1055d8c3a06SLeandro Lupori 		printf("ofw_initrd: initrd loaded at 0x%08lx-0x%08lx\n",
1065d8c3a06SLeandro Lupori 			start, end);
1075d8c3a06SLeandro Lupori 	}
1083ddc2cdeSBreno Leitao }
109