svn commit: r276506 - user/nwhitehorn/kboot/powerpc/kboot

Nathan Whitehorn nwhitehorn at FreeBSD.org
Thu Jan 1 18:07:59 UTC 2015


Author: nwhitehorn
Date: Thu Jan  1 18:07:56 2015
New Revision: 276506
URL: https://svnweb.freebsd.org/changeset/base/276506

Log:
  Create FDT from /proc/device-tree on Linux host. This is enough to get into
  KDB.

Added:
  user/nwhitehorn/kboot/powerpc/kboot/kbootfdt.c   (contents, props changed)
Modified:
  user/nwhitehorn/kboot/powerpc/kboot/Makefile
  user/nwhitehorn/kboot/powerpc/kboot/host_syscall.S
  user/nwhitehorn/kboot/powerpc/kboot/host_syscall.h
  user/nwhitehorn/kboot/powerpc/kboot/metadata.c
  user/nwhitehorn/kboot/powerpc/kboot/ppc64_elf_freebsd.c

Modified: user/nwhitehorn/kboot/powerpc/kboot/Makefile
==============================================================================
--- user/nwhitehorn/kboot/powerpc/kboot/Makefile	Thu Jan  1 16:56:15 2015	(r276505)
+++ user/nwhitehorn/kboot/powerpc/kboot/Makefile	Thu Jan  1 18:07:56 2015	(r276506)
@@ -10,7 +10,7 @@ INSTALLFLAGS=	-b
 
 # Architecture-specific loader code
 SRCS=		conf.c metadata.c vers.c main.c ppc64_elf_freebsd.c
-SRCS+=		host_syscall.S hostcons.c hostdisk.c kerneltramp.S
+SRCS+=		host_syscall.S hostcons.c hostdisk.c kerneltramp.S kbootfdt.c
 SRCS+=		ucmpdi2.c
 
 LOADER_DISK_SUPPORT?=	yes
@@ -21,7 +21,7 @@ LOADER_NET_SUPPORT?=	yes
 LOADER_NFS_SUPPORT?=	yes
 LOADER_TFTP_SUPPORT?=	no
 LOADER_GZIP_SUPPORT?=	yes
-LOADER_FDT_SUPPORT?=	no
+LOADER_FDT_SUPPORT?=	yes
 LOADER_BZIP2_SUPPORT?=	no
 
 .if ${LOADER_DISK_SUPPORT} == "yes"
@@ -54,6 +54,7 @@ CFLAGS+=	-DLOADER_TFTP_SUPPORT
 .if ${LOADER_FDT_SUPPORT} == "yes"
 CFLAGS+=	-I${.CURDIR}/../../fdt
 CFLAGS+=	-I${.OBJDIR}/../../fdt
+CFLAGS+=	-I${.CURDIR}/../../../contrib/libfdt
 CFLAGS+=	-DLOADER_FDT_SUPPORT
 LIBFDT=		${.OBJDIR}/../../fdt/libfdt.a
 .endif

Modified: user/nwhitehorn/kboot/powerpc/kboot/host_syscall.S
==============================================================================
--- user/nwhitehorn/kboot/powerpc/kboot/host_syscall.S	Thu Jan  1 16:56:15 2015	(r276505)
+++ user/nwhitehorn/kboot/powerpc/kboot/host_syscall.S	Thu Jan  1 18:07:56 2015	(r276506)
@@ -3,6 +3,10 @@
 ENTRY(host_read)
 	li %r0, 3 # SYS_read
 	sc
+	bso 1f
+	blr
+1:
+	li %r3, -1
 	blr
 
 ENTRY(host_write)
@@ -60,3 +64,8 @@ ENTRY(host_reboot)
 	sc
 	blr
 
+ENTRY(host_getdents)
+	li %r0,141 # SYS_getdents
+	sc
+	blr
+

Modified: user/nwhitehorn/kboot/powerpc/kboot/host_syscall.h
==============================================================================
--- user/nwhitehorn/kboot/powerpc/kboot/host_syscall.h	Thu Jan  1 16:56:15 2015	(r276505)
+++ user/nwhitehorn/kboot/powerpc/kboot/host_syscall.h	Thu Jan  1 18:07:56 2015	(r276506)
@@ -46,5 +46,6 @@ int host_select(int nfds, long *readfds,
     struct host_timeval *timeout);
 int kexec_load(vm_offset_t start);
 int host_reboot(int, int, int, void *);
+int host_getdents(int fd, void *dirp, int count);
 
 #endif

Added: user/nwhitehorn/kboot/powerpc/kboot/kbootfdt.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ user/nwhitehorn/kboot/powerpc/kboot/kbootfdt.c	Thu Jan  1 18:07:56 2015	(r276506)
@@ -0,0 +1,140 @@
+/*-
+ * Copyright (C) 2014 Nathan Whitehorn
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <fdt_platform.h>
+#include <libfdt.h>
+#include "bootstrap.h"
+#include "host_syscall.h"
+
+static void
+print_fdt(void *fdtp)
+{
+	int offset, depth, i;
+	const char *compat;
+
+	offset = fdt_path_offset(fdtp, "/");
+
+	for (depth = 0, offset = fdt_next_node(fdtp, offset, &depth);
+		offset >= 0; offset = fdt_next_node(fdtp, offset, &depth)) {
+                for (i = 1; i < depth; i++) printf("\t");
+                printf("%d: %s",offset, fdt_get_name(fdtp, offset, NULL));
+		compat = fdt_getprop(fdtp, offset, "compatible", NULL);
+                if (compat != NULL)
+                        printf(" (%s)", compat);
+                printf("\n");
+        }
+}
+
+static void
+add_node_to_fdt(void *buffer, const char *path, int fdt_offset)
+{
+        int child_offset, fd, pfd, error, dentsize;
+	char subpath[512];
+	void *propbuf;
+	ssize_t proplen;
+
+	struct host_dent {
+		unsigned long d_fileno;
+		unsigned long d_off;
+		unsigned short d_reclen;
+		char d_name[];
+		/* uint8_t	d_type; */
+	};
+	char dents[2048];
+	struct host_dent *dent;
+	int d_type;
+
+	fd = open(path, O_RDONLY);
+	while (1) {
+	    dentsize = host_getdents(fd, dents, sizeof(dents));
+	    if (dentsize <= 0)
+	      break;
+	    for (dent = (struct host_dent *)dents;
+	      (char *)dent < dents + dentsize;
+	      dent = (struct host_dent *)((void *)dent + dent->d_reclen)) {
+		sprintf(subpath, "%s/%s", path, dent->d_name);
+		if (strcmp(dent->d_name, ".") == 0 ||
+		    strcmp(dent->d_name, "..") == 0)
+			continue;
+		d_type = *((char *)(dent) + dent->d_reclen - 1);
+		if (d_type == 4 /* DT_DIR */) {
+			child_offset = fdt_add_subnode(buffer, fdt_offset,
+			    dent->d_name);
+			if (child_offset < 0) {
+				printf("Error %d adding node %s/%s, skipping\n",
+				    child_offset, path, dent->d_name);
+				continue;
+			}
+		
+			add_node_to_fdt(buffer, subpath, child_offset);
+		} else {
+			pfd = open(subpath, O_RDONLY);
+			propbuf = malloc(1024);
+			proplen = read(pfd, propbuf, 1024);
+			if (proplen < 0)
+				proplen = 0;
+			error = fdt_setprop(buffer, fdt_offset, dent->d_name,
+			    propbuf, proplen);
+			free(propbuf);
+			close(pfd);
+			if (error)
+				printf("Error %d adding property %s to "
+				    "node %d\n", error, dent->d_name,
+				    fdt_offset);
+		}
+	    }
+	}
+
+	close(fd);
+}
+
+int
+fdt_platform_load_dtb(void)
+{
+	void *buffer;
+	size_t buflen = 409600;
+	char path[255] = "/proc/device-tree";
+
+	buffer = malloc(buflen);
+	fdt_create_empty_tree(buffer, buflen);
+	add_node_to_fdt(buffer, path, fdt_path_offset(buffer, "/"));
+	fdt_pack(buffer);
+printf("Device tree is %d total bytes\n", fdt_totalsize(buffer));
+
+	fdt_load_dtb_addr(buffer);
+	
+	return (0);
+}
+
+void
+fdt_platform_fixups(void)
+{
+
+}
+

Modified: user/nwhitehorn/kboot/powerpc/kboot/metadata.c
==============================================================================
--- user/nwhitehorn/kboot/powerpc/kboot/metadata.c	Thu Jan  1 16:56:15 2015	(r276505)
+++ user/nwhitehorn/kboot/powerpc/kboot/metadata.c	Thu Jan  1 18:07:56 2015	(r276506)
@@ -242,7 +242,7 @@ md_copymodules(vm_offset_t addr, int ker
  * - Module metadata are formatted and placed in kernel space.
  */
 int
-md_load_dual(char *args, vm_offset_t *modulep, int kern64)
+md_load_dual(char *args, vm_offset_t *modulep, vm_offset_t *dtb, int kern64)
 {
     struct preloaded_file	*kfp;
     struct preloaded_file	*xp;
@@ -250,6 +250,7 @@ md_load_dual(char *args, vm_offset_t *mo
     vm_offset_t			kernend;
     vm_offset_t			addr;
     vm_offset_t			envp;
+    vm_offset_t			fdtp;
     vm_offset_t			size;
     uint64_t			scratch64;
     char			*rootdevname;
@@ -285,6 +286,11 @@ md_load_dual(char *args, vm_offset_t *mo
     /* pad to a page boundary */
     addr = roundup(addr, PAGE_SIZE);
 
+    /* Copy out FDT */
+    size = fdt_copy(addr);
+    *dtb = fdtp = addr;
+    addr = roundup(addr + size, PAGE_SIZE);
+
     kernend = 0;
     kfp = file_findfile(NULL, kern64 ? "elf64 kernel" : "elf32 kernel");
     if (kfp == NULL)
@@ -295,10 +301,13 @@ md_load_dual(char *args, vm_offset_t *mo
     if (kern64) {
 	scratch64 = envp;
 	file_addmetadata(kfp, MODINFOMD_ENVP, sizeof scratch64, &scratch64);
+	scratch64 = fdtp;
+	file_addmetadata(kfp, MODINFOMD_DTBP, sizeof scratch64, &scratch64);
 	scratch64 = kernend;
 	file_addmetadata(kfp, MODINFOMD_KERNEND, sizeof scratch64, &scratch64);
     } else {
 	file_addmetadata(kfp, MODINFOMD_ENVP, sizeof envp, &envp);
+	file_addmetadata(kfp, MODINFOMD_DTBP, sizeof fdtp, &fdtp);
 	file_addmetadata(kfp, MODINFOMD_KERNEND, sizeof kernend, &kernend);
     }
 
@@ -320,14 +329,14 @@ md_load_dual(char *args, vm_offset_t *mo
 }
 
 int
-md_load(char *args, vm_offset_t *modulep)
+md_load(char *args, vm_offset_t *modulep, vm_offset_t *dtb)
 {
-    return (md_load_dual(args, modulep, 0));
+    return (md_load_dual(args, modulep, dtb, 0));
 }
 
 int
-md_load64(char *args, vm_offset_t *modulep)
+md_load64(char *args, vm_offset_t *modulep, vm_offset_t *dtb)
 {
-    return (md_load_dual(args, modulep, 1));
+    return (md_load_dual(args, modulep, dtb, 1));
 }
 

Modified: user/nwhitehorn/kboot/powerpc/kboot/ppc64_elf_freebsd.c
==============================================================================
--- user/nwhitehorn/kboot/powerpc/kboot/ppc64_elf_freebsd.c	Thu Jan  1 16:56:15 2015	(r276505)
+++ user/nwhitehorn/kboot/powerpc/kboot/ppc64_elf_freebsd.c	Thu Jan  1 18:07:56 2015	(r276506)
@@ -62,7 +62,7 @@ int
 ppc64_elf_exec(struct preloaded_file *fp)
 {
 	struct file_metadata	*fmp;
-	vm_offset_t		mdp;
+	vm_offset_t		mdp, dtb;
 	Elf_Ehdr		*e;
 	int			error;
 	uint32_t		*trampoline;
@@ -77,13 +77,13 @@ ppc64_elf_exec(struct preloaded_file *fp
 	trampoline = malloc(szkerneltramp);
 	memcpy(trampoline, &kerneltramp, szkerneltramp);
 	trampoline[2] = e->e_entry;
-	trampoline[3] = 0; /* FDT */
 	trampoline[4] = 0; /* Phys. mem offset */
 	trampoline[5] = 0; /* OF entry point */
 
-	if ((error = md_load64(fp->f_args, &mdp)) != 0)
+	if ((error = md_load64(fp->f_args, &mdp, &dtb)) != 0)
 		return (error);
 
+	trampoline[3] = dtb;
 	trampoline[6] = mdp;
 	trampoline[7] = sizeof(mdp);
 	printf("Kernel entry at %#jx ...\n", e->e_entry);


More information about the svn-src-user mailing list