1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-12-18 10:35:55 +00:00

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)
This commit is contained in:
Michal Meloun 2016-03-26 06:59:01 +00:00
parent f5c06c61e4
commit e64c374375
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=297286
3 changed files with 75 additions and 8 deletions

View File

@ -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_params *abp)
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_params *abp)
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_params *abp)
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_params *abp)
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);

View File

@ -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);
}

View File

@ -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_ */