svn commit: r297286 - in head/sys: arm/arm dev/fdt

Michal Meloun mmel at FreeBSD.org
Sat Mar 26 06:59:03 UTC 2016


Author: mmel
Date: Sat Mar 26 06:59:01 2016
New Revision: 297286
URL: https://svnweb.freebsd.org/changeset/base/297286

Log:
  ARM: Parse command line delivered by U-Boot:
  - in atags
  - in DT blob (by using 'fdt chosen' U-Boot command)
  
  The command line must start with guard's string 'FreeBSD:' and can contain
  list of comma separated kenv strings. Also, boot modifier strings from
  boot.h are recognised and parsed into boothowto.
  
  The command line must be passed from U-Boot by setting of bootargs variable:
  'setenv bootargs FreeBSD:boot_single=1,vfs.root.mountfrom=ufs:/dev/ada0s1a'
  followed by 'fdt chosen' (only for DT based boot)

Modified:
  head/sys/arm/arm/machdep.c
  head/sys/dev/fdt/fdt_common.c
  head/sys/dev/fdt/fdt_common.h

Modified: head/sys/arm/arm/machdep.c
==============================================================================
--- head/sys/arm/arm/machdep.c	Sat Mar 26 06:57:36 2016	(r297285)
+++ head/sys/arm/arm/machdep.c	Sat Mar 26 06:59:01 2016	(r297286)
@@ -60,6 +60,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/bus.h>
 #include <sys/cons.h>
 #include <sys/cpu.h>
+#include <sys/ctype.h>
 #include <sys/efi.h>
 #include <sys/exec.h>
 #include <sys/imgact.h>
@@ -74,6 +75,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/pcpu.h>
 #include <sys/ptrace.h>
 #include <sys/reboot.h>
+#include <sys/boot.h>
 #include <sys/rwlock.h>
 #include <sys/sched.h>
 #include <sys/signalvar.h>
@@ -232,6 +234,7 @@ static struct pv_addr kernelstack;
 #if defined(LINUX_BOOT_ABI)
 #define LBABI_MAX_BANKS	10
 
+#define CMDLINE_GUARD "FreeBSD:"
 uint32_t board_id;
 struct arm_lbabi_tag *atag_list;
 char linux_command_line[LBABI_MAX_COMMAND_LINE + 1];
@@ -1029,6 +1032,53 @@ pcpu0_init(void)
 }
 
 #if defined(LINUX_BOOT_ABI)
+
+/* Convert the U-Boot command line into FreeBSD kenv and boot options. */
+static void
+cmdline_set_env(char *cmdline, const char *guard)
+{
+	char *cmdline_next, *env;
+	size_t size, guard_len;
+	int i;
+
+	size = strlen(cmdline);
+	/* Skip leading spaces. */
+	for (; isspace(*cmdline) && (size > 0); cmdline++)
+		size--;
+
+	/* Test and remove guard. */
+	if (guard != NULL && guard[0] != '\0') {
+		guard_len  =  strlen(guard);
+		if (strncasecmp(cmdline, guard, guard_len) != 0){
+			init_static_kenv(cmdline, 0);
+			return;
+
+			cmdline += guard_len;
+			size -= guard_len;
+		}
+	}
+
+	/* Skip leading spaces. */
+	for (; isspace(*cmdline) && (size > 0); cmdline++)
+		size--;
+
+	/* Replace ',' with '\0'. */
+	/* TODO: implement escaping for ',' character. */
+	cmdline_next = cmdline;
+	while(strsep(&cmdline_next, ",") != NULL)
+		;
+	init_static_kenv(cmdline, 0);
+	/* Parse boothowto. */
+	for (i = 0; howto_names[i].ev != NULL; i++) {
+		env = kern_getenv(howto_names[i].ev);
+		if (env != NULL) {
+			if (strtoul(env, NULL, 10) != 0)
+				boothowto |= howto_names[i].mask;
+			freeenv(env);
+		}
+	}
+}
+
 vm_offset_t
 linux_parse_boot_param(struct arm_boot_params *abp)
 {
@@ -1036,6 +1086,7 @@ linux_parse_boot_param(struct arm_boot_p
 	uint32_t revision;
 	uint64_t serial;
 	int size;
+	vm_offset_t lastaddr;
 #ifdef FDT
 	struct fdt_header *dtb_ptr;
 	uint32_t dtb_size;
@@ -1057,9 +1108,6 @@ linux_parse_boot_param(struct arm_boot_p
 		return (fake_preload_metadata(abp, dtb_ptr, dtb_size));
 	}
 #endif
-	/* Old, ATAG based boot must have board type set. */
-	if (abp->abp_r1 == 0)
-		return (0);
 
 	board_id = abp->abp_r1;
 	walker = (struct arm_lbabi_tag *)abp->abp_r2;
@@ -1089,10 +1137,9 @@ linux_parse_boot_param(struct arm_boot_p
 			board_set_revision(revision);
 			break;
 		case ATAG_CMDLINE:
-			/* XXX open question: Parse this for boothowto? */
 			size = ATAG_SIZE(walker) -
 			    sizeof(struct arm_lbabi_header);
-			size = min(size, sizeof(linux_command_line) - 1);
+			size = min(size, LBABI_MAX_COMMAND_LINE);
 			strncpy(linux_command_line, walker->u.tag_cmd.command,
 			    size);
 			linux_command_line[size] = '\0';
@@ -1107,9 +1154,9 @@ linux_parse_boot_param(struct arm_boot_p
 	bcopy(atag_list, atags,
 	    (char *)walker - (char *)atag_list + ATAG_SIZE(walker));
 
-	init_static_kenv(NULL, 0);
-
-	return fake_preload_metadata(abp, NULL, 0);
+	lastaddr = fake_preload_metadata(abp, NULL, 0);
+	cmdline_set_env(linux_command_line, CMDLINE_GUARD);
+	return lastaddr;
 }
 #endif
 
@@ -1785,6 +1832,12 @@ initarm(struct arm_boot_params *abp)
 	if (OF_init((void *)dtbp) != 0)
 		panic("OF_init failed with the found device tree");
 
+#if defined(LINUX_BOOT_ABI)
+	if (fdt_get_chosen_bootargs(linux_command_line,
+	    LBABI_MAX_COMMAND_LINE) == 0)
+		cmdline_set_env(linux_command_line, CMDLINE_GUARD);
+#endif
+
 #ifdef EFI
 	efihdr = (struct efi_map_header *)preload_search_info(kmdp,
 	    MODINFO_METADATA | MODINFOMD_EFI_MAP);

Modified: head/sys/dev/fdt/fdt_common.c
==============================================================================
--- head/sys/dev/fdt/fdt_common.c	Sat Mar 26 06:57:36 2016	(r297285)
+++ head/sys/dev/fdt/fdt_common.c	Sat Mar 26 06:59:01 2016	(r297286)
@@ -722,3 +722,16 @@ fdt_get_unit(device_t dev)
 
 	return (strtol(name,NULL,0));
 }
+
+int
+fdt_get_chosen_bootargs(char *bootargs, size_t max_size)
+{
+	phandle_t chosen;
+
+	chosen = OF_finddevice("/chosen");
+	if (chosen == -1)
+		return (ENXIO);
+	if (OF_getprop(chosen, "bootargs", bootargs, max_size) == -1)
+		return (ENXIO);
+	return (0);
+}
\ No newline at end of file

Modified: head/sys/dev/fdt/fdt_common.h
==============================================================================
--- head/sys/dev/fdt/fdt_common.h	Sat Mar 26 06:57:36 2016	(r297285)
+++ head/sys/dev/fdt/fdt_common.h	Sat Mar 26 06:59:01 2016	(r297286)
@@ -100,5 +100,6 @@ int fdt_parent_addr_cells(phandle_t);
 int fdt_reg_to_rl(phandle_t, struct resource_list *);
 int fdt_pm(phandle_t);
 int fdt_get_unit(device_t);
+int fdt_get_chosen_bootargs(char *bootargs, size_t max_size);
 
 #endif /* _FDT_COMMON_H_ */


More information about the svn-src-all mailing list