Date: Mon, 9 Dec 2019 08:38:01 -0600 From: Kyle Evans <kevans@freebsd.org> To: Michal Meloun <mmel@freebsd.org> Cc: src-committers <src-committers@freebsd.org>, svn-src-all <svn-src-all@freebsd.org>, svn-src-head <svn-src-head@freebsd.org> Subject: Re: svn commit: r355487 - in head/sys: arm64/arm64 arm64/include conf Message-ID: <CACNAnaEcn9_Wc=_z4MOP%2B4nh%2Bgu5N4%2BUusVnT1QjAGvJJgUyRA@mail.gmail.com> In-Reply-To: <201912071614.xB7GENQ3080793@repo.freebsd.org> References: <201912071614.xB7GENQ3080793@repo.freebsd.org>
next in thread | previous in thread | raw e-mail | index | archive | help
On Sat, Dec 7, 2019 at 10:14 AM Michal Meloun <mmel@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
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?CACNAnaEcn9_Wc=_z4MOP%2B4nh%2Bgu5N4%2BUusVnT1QjAGvJJgUyRA>