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