svn commit: r355487 - in head/sys: arm64/arm64 arm64/include conf

Kyle Evans kevans at freebsd.org
Mon Dec 9 14:38:13 UTC 2019


On Sat, Dec 7, 2019 at 10:14 AM Michal Meloun <mmel at freebsd.org> wrote:
>
> Author: mmel
> Date: Sat Dec  7 16:14:23 2019
> New Revision: 355487
> URL: https://svnweb.freebsd.org/changeset/base/355487
>
> Log:
>   Add support for booting kernel directly from U-Boot using booti command.
>
>   In some cases, like is locked bootstrap or device's inability to boot from
>   removable media, we cannot use standard boot sequence and is necessary to
>   boot kernel directly from U-Boot.
>
>   Discussed with:       jhibbits
>   MFC after:    1 month
>   Differential Revision:        https://reviews.freebsd.org/D13861
>
> Added:
>   head/sys/arm64/arm64/machdep_boot.c   (contents, props changed)
> Modified:
>   head/sys/arm64/arm64/locore.S
>   head/sys/arm64/arm64/machdep.c
>   head/sys/arm64/include/machdep.h
>   head/sys/conf/Makefile.arm64
>   head/sys/conf/files.arm64
>   head/sys/conf/options.arm64
>
> [... snip ...]
> Added: head/sys/arm64/arm64/machdep_boot.c
> ==============================================================================
> --- /dev/null   00:00:00 1970   (empty, because file is newly added)
> +++ head/sys/arm64/arm64/machdep_boot.c Sat Dec  7 16:14:23 2019        (r355487)
> @@ -0,0 +1,254 @@
> +/*-
> + * Copyright (c) 2004 Olivier Houchard
> + * Copyright (c) 1994-1998 Mark Brinicombe.
> + * Copyright (c) 1994 Brini.
> + * 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 AND CONTRIBUTORS ``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 THE AUTHOR OR CONTRIBUTORS 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 "opt_platform.h"
> +
> +#include <sys/cdefs.h>
> +__FBSDID("$FreeBSD$");
> +
> +#include <sys/param.h>
> +#include <sys/systm.h>
> +#include <sys/ctype.h>
> +#include <sys/linker.h>
> +#include <sys/reboot.h>
> +#include <sys/sysctl.h>
> +#ifdef FDT
> +#include <sys/boot.h>
> +#endif
> +
> +#include <machine/cpu.h>
> +#include <machine/machdep.h>
> +#include <machine/metadata.h>
> +#include <machine/vmparam.h>
> +
> +#ifdef FDT
> +#include <contrib/libfdt/libfdt.h>
> +#include <dev/fdt/fdt_common.h>
> +#endif
> +
> +extern int *end;
> +static char *loader_envp;
> +static char static_kenv[4096];
> +
> +
> +#ifdef FDT
> +#define        CMDLINE_GUARD "FreeBSD:"
> +#define        LBABI_MAX_COMMAND_LINE 512
> +static char linux_command_line[LBABI_MAX_COMMAND_LINE + 1];
> +#endif
> +
> +/*
> + * Fake up a boot descriptor table
> + */
> + #define PRELOAD_PUSH_VALUE(type, value) do {          \
> +       *(type *)(preload_ptr + size) = (value);        \
> +       size += sizeof(type);                           \
> +} while (0)
> +
> + #define PRELOAD_PUSH_STRING(str) do {                 \
> +       uint32_t ssize;                                 \
> +       ssize = strlen(str) + 1;                        \
> +       PRELOAD_PUSH_VALUE(uint32_t, ssize);            \
> +       strcpy((char*)(preload_ptr + size), str);       \
> +       size += ssize;                                  \
> +       size = roundup(size, sizeof(u_long));           \
> +} while (0)
> +
> +
> +/* Build minimal set of metatda. */
> +static vm_offset_t
> +fake_preload_metadata(void *dtb_ptr, size_t dtb_size)
> +{
> +#ifdef DDB
> +       vm_offset_t zstart = 0, zend = 0;
> +#endif
> +       vm_offset_t lastaddr;
> +       static char fake_preload[256];
> +       caddr_t preload_ptr;
> +       size_t size;
> +
> +       preload_ptr = (caddr_t)&fake_preload[0];
> +       size = 0;
> +
> +       PRELOAD_PUSH_VALUE(uint32_t, MODINFO_NAME);
> +       PRELOAD_PUSH_STRING("kernel");
> +
> +       PRELOAD_PUSH_VALUE(uint32_t, MODINFO_TYPE);
> +       PRELOAD_PUSH_STRING("elf kernel");
> +
> +       PRELOAD_PUSH_VALUE(uint32_t, MODINFO_ADDR);
> +       PRELOAD_PUSH_VALUE(uint32_t, sizeof(vm_offset_t));
> +       PRELOAD_PUSH_VALUE(uint64_t, VM_MIN_KERNEL_ADDRESS);
> +
> +       PRELOAD_PUSH_VALUE(uint32_t, MODINFO_SIZE);
> +       PRELOAD_PUSH_VALUE(uint32_t, sizeof(size_t));
> +       PRELOAD_PUSH_VALUE(uint64_t, (size_t)(&end - VM_MIN_KERNEL_ADDRESS));
> +#ifdef DDB
> +       if (*(uint64_t *)VM_MIN_KERNEL_ADDRESS == MAGIC_TRAMP_NUMBER) {
> +               PRELOAD_PUSH_VALUE(uint32_t, MODINFO_METADATA|MODINFOMD_SSYM);
> +               PRELOAD_PUSH_VALUE(uint32_t, sizeof(vm_offset_t));
> +               PRELOAD_PUSH_VALUE(uint64_t,
> +                   *(uint64_t *)(VM_MIN_KERNEL_ADDRESS + 4));
> +
> +               PRELOAD_PUSH_VALUE(uint32_t, MODINFO_METADATA | MODINFOMD_ESYM);
> +               PRELOAD_PUSH_VALUE(uint32_t, sizeof(vm_offset_t));
> +               PRELOAD_PUSH_VALUE(uint64_t,
> +                   *(uint64_t *)(VM_MIN_KERNEL_ADDRESS + 8));
> +
> +               lastaddr = *(uint64_t *)(VM_MIN_KERNEL_ADDRESS + 8);
> +               zend = lastaddr;
> +               zstart = *(uint64_t *)(VM_MIN_KERNEL_ADDRESS + 4);
> +               db_fetch_ksymtab(zstart, zend);
> +       } else
> +#endif
> +               lastaddr = (vm_offset_t)&end;
> +       if (dtb_ptr != NULL) {
> +               /* Copy DTB to KVA space and insert it into module chain. */
> +               lastaddr = roundup(lastaddr, sizeof(int));
> +               PRELOAD_PUSH_VALUE(uint32_t, MODINFO_METADATA | MODINFOMD_DTBP);
> +               PRELOAD_PUSH_VALUE(uint32_t, sizeof(uint64_t));
> +               PRELOAD_PUSH_VALUE(uint64_t, (uint64_t)lastaddr);
> +               memmove((void *)lastaddr, dtb_ptr, dtb_size);
> +               lastaddr += dtb_size;
> +               lastaddr = roundup(lastaddr, sizeof(int));
> +       }
> +       /* End marker */
> +       PRELOAD_PUSH_VALUE(uint32_t, 0);
> +       PRELOAD_PUSH_VALUE(uint32_t, 0);
> +
> +       preload_metadata = (caddr_t)(uintptr_t)fake_preload;
> +
> +       init_static_kenv(NULL, 0);
> +
> +       return (lastaddr);
> +}
> +
> +#ifdef FDT
> +
> +/* Convert the U-Boot command line into FreeBSD kenv and boot options. */
> +static void
> +cmdline_set_env(char *cmdline, const char *guard)
> +{
> +       size_t guard_len;
> +
> +       /* Skip leading spaces. */
> +       while (isspace(*cmdline))
> +               cmdline++;
> +
> +       /* Test and remove guard. */
> +       if (guard != NULL && guard[0] != '\0') {
> +               guard_len  =  strlen(guard);
> +               if (strncasecmp(cmdline, guard, guard_len) != 0)
> +                       return;
> +               cmdline += guard_len;
> +       }
> +
> +       boothowto |= boot_parse_cmdline(cmdline);
> +}
> +
> +void
> +parse_fdt_bootargs(void)
> +{
> +
> +       if (loader_envp == NULL && fdt_get_chosen_bootargs(linux_command_line,
> +           LBABI_MAX_COMMAND_LINE) == 0) {
> +               init_static_kenv(static_kenv, sizeof(static_kenv));
> +               cmdline_set_env(linux_command_line, CMDLINE_GUARD);
> +       }
> +}
> +
> +#endif
> +
> +#if defined(LINUX_BOOT_ABI) && defined(FDT)
> +static vm_offset_t
> +linux_parse_boot_param(struct arm64_bootparams *abp)
> +{
> +       struct fdt_header *dtb_ptr;
> +       size_t dtb_size;
> +
> +       if (abp->modulep == 0)
> +               return (0);
> +       /* Test if modulep point to valid DTB. */
> +       dtb_ptr = (struct fdt_header *)abp->modulep;
> +       if (fdt_check_header(dtb_ptr) != 0)
> +               return (0);
> +       dtb_size = fdt_totalsize(dtb_ptr);
> +       return (fake_preload_metadata(dtb_ptr, dtb_size));
> +}
> +
> +#endif
> +
> +static vm_offset_t
> +freebsd_parse_boot_param(struct arm64_bootparams *abp)
> +{
> +       vm_offset_t lastaddr = 0;
> +       void *kmdp;
> +#ifdef DDB
> +       vm_offset_t ksym_start;
> +       vm_offset_t ksym_end;
> +#endif
> +
> +       if (abp->modulep == 0)
> +               return (0);
> +
> +       preload_metadata = (caddr_t)(uintptr_t)(abp->modulep);
> +       kmdp = preload_search_by_type("elf kernel");
> +       if (kmdp == NULL)
> +               return (0);
> +
> +       boothowto = MD_FETCH(kmdp, MODINFOMD_HOWTO, int);
> +       loader_envp = MD_FETCH(kmdp, MODINFOMD_ENVP, char *);
> +       init_static_kenv(static_kenv, 0);

This should read "loader_envp" instead of "static_kenv" -- as written,
it stomps over the kenv provided by loader.

> [ ... snip ...]

Thanks,

Kyle Evans


More information about the svn-src-head mailing list