Module Name: src
Committed By: thorpej
Date: Sun Apr 21 22:30:41 UTC 2019
Modified Files:
src/sys/stand/efiboot: Makefile.efiboot boot.c efiboot.c efiboot.h
efienv.c efienv.h efifdt.c efifdt.h exec.c version
Log Message:
- Add support for a boot configuration file, defaulting to /etc/efiboot.plist.
- Add support for pre-loading EFI environment variables from efiboot.plist.
- Add support for device tree overlays specified in efiboot.plist.
(Man page for efiboot forthcoming.)
To generate a diff of this commit:
cvs rdiff -u -r1.6 -r1.7 src/sys/stand/efiboot/Makefile.efiboot
cvs rdiff -u -r1.17 -r1.18 src/sys/stand/efiboot/boot.c
cvs rdiff -u -r1.15 -r1.16 src/sys/stand/efiboot/efiboot.c
cvs rdiff -u -r1.9 -r1.10 src/sys/stand/efiboot/efiboot.h \
src/sys/stand/efiboot/exec.c src/sys/stand/efiboot/version
cvs rdiff -u -r1.3 -r1.4 src/sys/stand/efiboot/efienv.c
cvs rdiff -u -r1.1 -r1.2 src/sys/stand/efiboot/efienv.h
cvs rdiff -u -r1.14 -r1.15 src/sys/stand/efiboot/efifdt.c
cvs rdiff -u -r1.4 -r1.5 src/sys/stand/efiboot/efifdt.h
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/stand/efiboot/Makefile.efiboot
diff -u src/sys/stand/efiboot/Makefile.efiboot:1.6 src/sys/stand/efiboot/Makefile.efiboot:1.7
--- src/sys/stand/efiboot/Makefile.efiboot:1.6 Fri Oct 12 22:08:04 2018
+++ src/sys/stand/efiboot/Makefile.efiboot Sun Apr 21 22:30:41 2019
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile.efiboot,v 1.6 2018/10/12 22:08:04 jmcneill Exp $
+# $NetBSD: Makefile.efiboot,v 1.7 2019/04/21 22:30:41 thorpej Exp $
S= ${.CURDIR}/../../..
@@ -26,7 +26,7 @@ SOURCES+= efiboot.c efichar.c efidev.c e
.PATH: ${S}/external/bsd/libfdt/dist
CPPFLAGS+= -I${S}/external/bsd/libfdt/dist
-SOURCES+= fdt.c fdt_addresses.c fdt_empty_tree.c
+SOURCES+= fdt.c fdt_addresses.c fdt_empty_tree.c fdt_overlay.c
SOURCES+= fdt_ro.c fdt_rw.c fdt_strerror.c fdt_sw.c fdt_wip.c
SRCS= ${SOURCES} ${EXTRA_SOURCES}
@@ -51,6 +51,7 @@ LDFLAGS+= -nostdlib -T${LDSCRIPT} -Bsymb
CPPFLAGS+= -I$S -I${.CURDIR} -I${.CURDIR}/../common -I$S/lib/libsa
CPPFLAGS+= -I${.OBJDIR}
CPPFLAGS+= -I${.CURDIR}/../../lib
+CPPFLAGS+= -I${S}/../common/include
COPTS+= -fpic -g -O2
COPTS+= -fshort-wchar -fno-strict-aliasing
@@ -77,6 +78,7 @@ CPPFLAGS+= -DSUPPORT_DHCP
CPPFLAGS+= -DSUPPORT_TFTP
CPPFLAGS+= -DLIBSA_ENABLE_LS_OP
+#CPPFLAGS+= -DEFIBOOT_DEBUG
#CPPFLAGS+= -DARP_DEBUG
#CPPFLAGS+= -DBOOTP_DEBUG
#CPPFLAGS+= -DNET_DEBUG
Index: src/sys/stand/efiboot/boot.c
diff -u src/sys/stand/efiboot/boot.c:1.17 src/sys/stand/efiboot/boot.c:1.18
--- src/sys/stand/efiboot/boot.c:1.17 Sat Apr 20 11:28:53 2019
+++ src/sys/stand/efiboot/boot.c Sun Apr 21 22:30:41 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: boot.c,v 1.17 2019/04/20 11:28:53 jmcneill Exp $ */
+/* $NetBSD: boot.c,v 1.18 2019/04/21 22:30:41 thorpej Exp $ */
/*-
* Copyright (c) 2016 Kimihiro Nonaka <[email protected]>
@@ -72,6 +72,7 @@ static const char *efi_memory_type[] = {
static char default_device[32];
static char initrd_path[255];
static char dtb_path[255];
+static char efibootplist_path[255];
static char netbsd_path[255];
static char netbsd_args[255];
@@ -84,6 +85,7 @@ int set_bootargs(const char *);
void command_boot(char *);
void command_dev(char *);
void command_dtb(char *);
+void command_plist(char *);
void command_initrd(char *);
void command_ls(char *);
void command_mem(char *);
@@ -99,6 +101,7 @@ const struct boot_command commands[] = {
{ "boot", command_boot, "boot [dev:][filename] [args]\n (ex. \"hd0a:\\netbsd.old -s\"" },
{ "dev", command_dev, "dev" },
{ "dtb", command_dtb, "dtb [dev:][filename]" },
+ { "plist", command_plist, "plist [dev:][filename]" },
{ "initrd", command_initrd, "initrd [dev:][filename]" },
{ "ls", command_ls, "ls [hdNn:/path]" },
{ "mem", command_mem, "mem" },
@@ -166,6 +169,13 @@ command_dtb(char *arg)
}
void
+command_plist(char *arg)
+{
+ if (set_efibootplist_path(arg) == 0)
+ load_efibootplist(false);
+}
+
+void
command_initrd(char *arg)
{
set_initrd_path(arg);
@@ -324,6 +334,20 @@ get_dtb_path(void)
}
int
+set_efibootplist_path(const char *arg)
+{
+ if (strlen(arg) + 1 > sizeof(efibootplist_path))
+ return ERANGE;
+ strcpy(efibootplist_path, arg);
+ return 0;
+}
+
+char *get_efibootplist_path(void)
+{
+ return efibootplist_path;
+}
+
+int
set_bootfile(const char *arg)
{
if (strlen(arg) + 1 > sizeof(netbsd_path))
@@ -354,6 +378,21 @@ read_env(void)
{
char *s;
+ s = efi_env_get("efibootplist");
+ if (s) {
+#ifdef EFIBOOT_DEBUG
+ printf(">> Setting efiboot.plist path to '%s' from environment\n", s);
+#endif
+ set_efibootplist_path(s);
+ FreePool(s);
+ }
+
+ /*
+ * Read the efiboot.plist now as it may contain additional
+ * environment variables.
+ */
+ load_efibootplist(true);
+
s = efi_env_get("fdtfile");
if (s) {
#ifdef EFIBOOT_DEBUG
Index: src/sys/stand/efiboot/efiboot.c
diff -u src/sys/stand/efiboot/efiboot.c:1.15 src/sys/stand/efiboot/efiboot.c:1.16
--- src/sys/stand/efiboot/efiboot.c:1.15 Sat Apr 20 11:23:16 2019
+++ src/sys/stand/efiboot/efiboot.c Sun Apr 21 22:30:41 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: efiboot.c,v 1.15 2019/04/20 11:23:16 jmcneill Exp $ */
+/* $NetBSD: efiboot.c,v 1.16 2019/04/21 22:30:41 thorpej Exp $ */
/*-
* Copyright (c) 2018 Jared McNeill <[email protected]>
@@ -56,6 +56,8 @@ static EFI_EVENT delay_ev = 0;
EFI_STATUS EFIAPI efi_main(EFI_HANDLE, EFI_SYSTEM_TABLE *);
+prop_dictionary_t efibootplist;
+
EFI_STATUS EFIAPI
efi_main(EFI_HANDLE imageHandle, EFI_SYSTEM_TABLE *systemTable)
{
@@ -180,6 +182,10 @@ efi_cleanup(void)
UINTN nentries, mapkey, descsize;
UINT32 descver;
+ if (efibootplist) {
+ prop_object_release(efibootplist);
+ }
+
memmap = LibMemoryMap(&nentries, &mapkey, &descsize, &descver);
status = uefi_call_wrapper(BS->ExitBootServices, 2, IH, mapkey);
Index: src/sys/stand/efiboot/efiboot.h
diff -u src/sys/stand/efiboot/efiboot.h:1.9 src/sys/stand/efiboot/efiboot.h:1.10
--- src/sys/stand/efiboot/efiboot.h:1.9 Thu Nov 15 23:52:33 2018
+++ src/sys/stand/efiboot/efiboot.h Sun Apr 21 22:30:41 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: efiboot.h,v 1.9 2018/11/15 23:52:33 jmcneill Exp $ */
+/* $NetBSD: efiboot.h,v 1.10 2019/04/21 22:30:41 thorpej Exp $ */
/*-
* Copyright (c) 2016 Kimihiro Nonaka <[email protected]>
@@ -35,6 +35,8 @@
#include <loadfile.h>
#include <net.h>
+#include <prop/proplib.h>
+
#include "efiboot_machdep.h"
struct boot_command {
@@ -60,6 +62,8 @@ int set_initrd_path(const char *);
char *get_initrd_path(void);
int set_dtb_path(const char *);
char *get_dtb_path(void);
+int set_efibootplist_path(const char *);
+char *get_efibootplist_path(void);
/* console.c */
int ischar(void);
@@ -73,6 +77,7 @@ void efi_exit(void);
void efi_delay(int);
void efi_reboot(void);
extern int howto;
+extern prop_dictionary_t efibootplist;
/* efichar.c */
size_t ucs2len(const CHAR16 *);
@@ -101,6 +106,7 @@ bool efi_pxe_match_booted_interface(cons
/* exec.c */
int exec_netbsd(const char *, const char *);
+void load_efibootplist(bool);
/* panic.c */
__dead VOID Panic(IN CHAR16 *, ...);
Index: src/sys/stand/efiboot/exec.c
diff -u src/sys/stand/efiboot/exec.c:1.9 src/sys/stand/efiboot/exec.c:1.10
--- src/sys/stand/efiboot/exec.c:1.9 Sat Mar 30 12:47:53 2019
+++ src/sys/stand/efiboot/exec.c Sun Apr 21 22:30:41 2019
@@ -1,6 +1,7 @@
-/* $NetBSD: exec.c,v 1.9 2019/03/30 12:47:53 jmcneill Exp $ */
+/* $NetBSD: exec.c,v 1.10 2019/04/21 22:30:41 thorpej Exp $ */
/*-
+ * Copyright (c) 2019 Jason R. Thorpe
* Copyright (c) 2018 Jared McNeill <[email protected]>
* All rights reserved.
*
@@ -27,6 +28,7 @@
*/
#include "efiboot.h"
+#include "efienv.h"
#include "efifdt.h"
#include "efiacpi.h"
@@ -41,11 +43,13 @@ static EFI_PHYSICAL_ADDRESS initrd_addr,
static u_long initrd_size = 0, dtb_size = 0;
static int
-load_file(char *path, EFI_PHYSICAL_ADDRESS *paddr, u_long *psize)
+load_file(const char *path, u_long extra, bool quiet_errors,
+ EFI_PHYSICAL_ADDRESS *paddr, u_long *psize)
{
EFI_STATUS status;
struct stat st;
ssize_t len;
+ ssize_t expectedlen;
int fd;
if (strlen(path) == 0)
@@ -53,7 +57,10 @@ load_file(char *path, EFI_PHYSICAL_ADDRE
fd = open(path, 0);
if (fd < 0) {
- printf("boot: failed to open %s: %s\n", path, strerror(errno));
+ if (!quiet_errors) {
+ printf("boot: failed to open %s: %s\n", path,
+ strerror(errno));
+ }
return errno;
}
if (fstat(fd, &st) < 0) {
@@ -62,12 +69,15 @@ load_file(char *path, EFI_PHYSICAL_ADDRE
return errno;
}
if (st.st_size == 0) {
- printf("boot: empty file %s\n", path);
+ if (!quiet_errors) {
+ printf("boot: empty file %s\n", path);
+ }
close(fd);
return EINVAL;
}
- *psize = st.st_size;
+ expectedlen = st.st_size;
+ *psize = st.st_size + extra;
#ifdef EFIBOOT_ALLOCATE_MAX_ADDRESS
*paddr = EFIBOOT_ALLOCATE_MAX_ADDRESS;
@@ -82,18 +92,21 @@ load_file(char *path, EFI_PHYSICAL_ADDRE
printf("Failed to allocate %lu bytes for %s (error %lu)\n",
*psize, path, (u_long)status);
close(fd);
+ *paddr = 0;
return ENOMEM;
}
printf("boot: loading %s ", path);
- len = read(fd, (void *)(uintptr_t)*paddr, *psize);
+ len = read(fd, (void *)(uintptr_t)*paddr, expectedlen);
close(fd);
- if (len != *psize) {
- if (len < 0)
+ if (len != expectedlen) {
+ if (len < 0) {
printf(": %s\n", strerror(errno));
- else
- printf(": returned %ld (expected %ld)\n", len, *psize);
+ } else {
+ printf(": returned %ld (expected %ld)\n", len,
+ expectedlen);
+ }
return EIO;
}
@@ -104,6 +117,155 @@ load_file(char *path, EFI_PHYSICAL_ADDRE
return 0;
}
+static const char default_efibootplist_path[] = "/etc/efiboot.plist";
+
+/* This is here because load_file() is here. */
+void
+load_efibootplist(bool default_fallback)
+{
+ EFI_PHYSICAL_ADDRESS plist_addr = 0;
+ u_long plist_size = 0;
+ prop_dictionary_t plist = NULL, oplist = NULL;
+ bool load_quietly = false;
+
+ const char *path = get_efibootplist_path();
+ if (path == NULL || strlen(path) == 0) {
+ if (!default_fallback)
+ return;
+ path = default_efibootplist_path;
+ load_quietly = true;
+ }
+
+ /*
+ * Fudge the size so we can ensure the resulting buffer
+ * is NUL-terminated for convenience.
+ */
+ if (load_file(path, 1, load_quietly, &plist_addr, &plist_size) != 0 ||
+ plist_addr == 0) {
+ /* Error messages have already been displayed. */
+ goto out;
+ }
+ char *plist_buf = (char *)((uintptr_t)plist_addr);
+ plist_buf[plist_size - 1] = '\0';
+
+ plist = prop_dictionary_internalize(plist_buf);
+ if (plist == NULL) {
+ printf("boot: unable to parse plist '%s'\n", path);
+ goto out;
+ }
+
+out:
+ oplist = efibootplist;
+
+ /*
+ * If we had a failure, create an empty one for
+ * convenience. But a failure should not clobber
+ * an in-memory plist we already have.
+ */
+ if (plist == NULL &&
+ (oplist == NULL || prop_dictionary_count(oplist) == 0))
+ plist = prop_dictionary_create();
+
+#ifdef EFIBOOT_DEBUG
+ printf(">> load_efibootplist: oplist = 0x%lx, plist = 0x%lx\n",
+ (u_long)oplist, (u_long)plist);
+#endif
+
+ if (plist_addr) {
+ uefi_call_wrapper(BS->FreePages, 2, plist_addr,
+ EFI_SIZE_TO_PAGES(plist_size));
+ }
+
+ if (plist) {
+ efibootplist = plist;
+ efi_env_from_efibootplist();
+
+ if (oplist)
+ prop_object_release(oplist);
+ }
+}
+
+static void
+apply_overlay(void *dtbo)
+{
+
+ if (!efi_fdt_overlay_is_compatible(dtbo)) {
+ printf("boot: incompatible overlay\n");
+ }
+
+ int fdterr;
+
+ if (efi_fdt_overlay_apply(dtbo, &fdterr) != 0) {
+ printf("boot: error %d applying overlay\n", fdterr);
+ }
+}
+
+static void
+apply_overlay_file(const char *path)
+{
+ EFI_PHYSICAL_ADDRESS dtbo_addr;
+ u_long dtbo_size;
+
+ if (strlen(path) == 0)
+ return;
+
+ if (load_file(path, 0, false, &dtbo_addr, &dtbo_size) != 0 ||
+ dtbo_addr == 0) {
+ /* Error messages have already been displayed. */
+ goto out;
+ }
+
+ apply_overlay((void *)(uintptr_t)dtbo_addr);
+
+out:
+ if (dtbo_addr) {
+ uefi_call_wrapper(BS->FreePages, 2, dtbo_addr,
+ EFI_SIZE_TO_PAGES(dtbo_size));
+ }
+}
+
+#define DT_OVERLAYS_PROP "device-tree-overlays"
+
+static void
+load_fdt_overlays(void)
+{
+ /*
+ * We support loading device tree overlays specified in efiboot.plist
+ * using the following schema:
+ *
+ * <key>device-tree-overlays</key>
+ * <array>
+ * <string>/path/to/some/overlay.dtbo</string>
+ * <string>hd0e:/some/other/overlay.dtbo</string>
+ * </array>
+ *
+ * The overlays are loaded in array order.
+ */
+ prop_array_t overlays = prop_dictionary_get(efibootplist,
+ DT_OVERLAYS_PROP);
+ if (overlays == NULL) {
+#ifdef EFIBOOT_DEBUG
+ printf("boot: no device-tree-overlays\n");
+#endif
+ return;
+ }
+ if (prop_object_type(overlays) != PROP_TYPE_ARRAY) {
+ printf("boot: invalid %s\n", DT_OVERLAYS_PROP);
+ return;
+ }
+
+ prop_object_iterator_t iter = prop_array_iterator(overlays);
+ prop_string_t pathobj;
+ while ((pathobj = prop_object_iterator_next(iter)) != NULL) {
+ if (prop_object_type(pathobj) != PROP_TYPE_STRING) {
+ printf("boot: invalid %s entry\n", DT_OVERLAYS_PROP);
+ continue;
+ }
+ apply_overlay_file(prop_string_cstring_nocopy(pathobj));
+ }
+ prop_object_iterator_release(iter);
+}
+
int
exec_netbsd(const char *fname, const char *args)
{
@@ -112,8 +274,8 @@ exec_netbsd(const char *fname, const cha
EFI_STATUS status;
int fd, ohowto;
- load_file(get_initrd_path(), &initrd_addr, &initrd_size);
- load_file(get_dtb_path(), &dtb_addr, &dtb_size);
+ load_file(get_initrd_path(), 0, false, &initrd_addr, &initrd_size);
+ load_file(get_dtb_path(), 0, false, &dtb_addr, &dtb_size);
memset(marks, 0, sizeof(marks));
ohowto = howto;
@@ -165,6 +327,7 @@ exec_netbsd(const char *fname, const cha
if (efi_fdt_size() > 0) {
efi_fdt_init((marks[MARK_END] + FDT_ALIGN) & ~FDT_ALIGN, FDT_ALIGN + 1);
+ load_fdt_overlays();
efi_fdt_initrd(initrd_addr, initrd_size);
efi_fdt_bootargs(args);
efi_fdt_memory_map();
Index: src/sys/stand/efiboot/version
diff -u src/sys/stand/efiboot/version:1.9 src/sys/stand/efiboot/version:1.10
--- src/sys/stand/efiboot/version:1.9 Fri Jan 18 19:41:03 2019
+++ src/sys/stand/efiboot/version Sun Apr 21 22:30:41 2019
@@ -1,4 +1,4 @@
-$NetBSD: version,v 1.9 2019/01/18 19:41:03 skrll Exp $
+$NetBSD: version,v 1.10 2019/04/21 22:30:41 thorpej Exp $
NOTE ANY CHANGES YOU MAKE TO THE EFI BOOTLOADER HERE. The format of this
file is important - make sure the entries are appended on end, last item
@@ -13,3 +13,4 @@ is taken as the current.
1.6: Add GPT support.
1.7: Add NFS support.
1.8: Add support for "bootargs" environment variable.
+1.9: Add support for efiboot.plist and loading device tree overlays.
Index: src/sys/stand/efiboot/efienv.c
diff -u src/sys/stand/efiboot/efienv.c:1.3 src/sys/stand/efiboot/efienv.c:1.4
--- src/sys/stand/efiboot/efienv.c:1.3 Sat Mar 30 12:47:53 2019
+++ src/sys/stand/efiboot/efienv.c Sun Apr 21 22:30:41 2019
@@ -1,6 +1,7 @@
-/* $NetBSD: efienv.c,v 1.3 2019/03/30 12:47:53 jmcneill Exp $ */
+/* $NetBSD: efienv.c,v 1.4 2019/04/21 22:30:41 thorpej Exp $ */
/*-
+ * Copyright (c) 2019 Jason R. Thorpe
* Copyright (c) 2018 Jared McNeill <[email protected]>
* All rights reserved.
*
@@ -35,6 +36,69 @@
static EFI_GUID EfibootVendorGuid = EFIBOOT_VENDOR_GUID;
void
+efi_env_from_efibootplist(void)
+{
+ /*
+ * We support pre-loading the EFI environment from efiboot.plist
+ * using the following schema:
+ *
+ * <key>environment-variables</key>
+ * <dict>
+ * <key>varname1</key>
+ * <string>value_for_varname1</string>
+ * <key>varname2</key>
+ * <string>value_for_varname2</string>
+ * </dict>
+ *
+ * Only string values are supported.
+ */
+ prop_dictionary_t environment;
+ prop_dictionary_keysym_t key;
+ prop_string_t value;
+ prop_object_iterator_t iter;
+
+ const char *env_key;
+ char *env_value;
+
+ environment = prop_dictionary_get(efibootplist,
+ "environment-variables");
+ if (environment == NULL)
+ return;
+
+ iter = prop_dictionary_iterator(environment);
+ if (iter == NULL)
+ goto failed;
+
+ while ((key = prop_object_iterator_next(iter)) != NULL) {
+ value = prop_dictionary_get_keysym(environment, key);
+ if (value == NULL) {
+ printf("boot: env: failed to get value for '%s'\n",
+ prop_dictionary_keysym_cstring_nocopy(key));
+ continue;
+ }
+ if (prop_object_type(value) != PROP_TYPE_STRING) {
+ printf("boot: env: value for '%s' is not a string\n",
+ prop_dictionary_keysym_cstring_nocopy(key));
+ continue;
+ }
+ /* XXX __UNCONST because gnuefi */
+ env_key = prop_dictionary_keysym_cstring_nocopy(key);;
+ env_value = __UNCONST(prop_string_cstring_nocopy(value));;
+#ifdef EFIBOOT_DEBUG
+ printf(">> efiboot.plist env: '%s' = '%s'\n", env_key,
+ env_value);
+#endif
+ efi_env_set(env_key, env_value);
+ }
+ prop_object_iterator_release(iter);
+
+ return;
+
+ failed:
+ printf("boot: failed to load environment from efiboot.plist");
+}
+
+void
efi_env_set(const char *key, char *val)
{
EFI_STATUS status;
Index: src/sys/stand/efiboot/efienv.h
diff -u src/sys/stand/efiboot/efienv.h:1.1 src/sys/stand/efiboot/efienv.h:1.2
--- src/sys/stand/efiboot/efienv.h:1.1 Sun Sep 9 17:55:22 2018
+++ src/sys/stand/efiboot/efienv.h Sun Apr 21 22:30:41 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: efienv.h,v 1.1 2018/09/09 17:55:22 jmcneill Exp $ */
+/* $NetBSD: efienv.h,v 1.2 2019/04/21 22:30:41 thorpej Exp $ */
/*-
* Copyright (c) 2018 Jared McNeill <[email protected]>
@@ -26,6 +26,7 @@
* SUCH DAMAGE.
*/
+void efi_env_from_efibootplist(void);
void efi_env_set(const char *, char *);
char *efi_env_get(const char *);
void efi_env_clear(const char *);
Index: src/sys/stand/efiboot/efifdt.c
diff -u src/sys/stand/efiboot/efifdt.c:1.14 src/sys/stand/efiboot/efifdt.c:1.15
--- src/sys/stand/efiboot/efifdt.c:1.14 Thu Nov 15 23:52:33 2018
+++ src/sys/stand/efiboot/efifdt.c Sun Apr 21 22:30:41 2019
@@ -1,6 +1,7 @@
-/* $NetBSD: efifdt.c,v 1.14 2018/11/15 23:52:33 jmcneill Exp $ */
+/* $NetBSD: efifdt.c,v 1.15 2019/04/21 22:30:41 thorpej Exp $ */
/*-
+ * Copyright (c) 2019 Jason R. Thorpe
* Copyright (c) 2018 Jared McNeill <[email protected]>
* All rights reserved.
*
@@ -87,6 +88,53 @@ efi_fdt_size(void)
return fdt_data == NULL ? 0 : fdt_totalsize(fdt_data);
}
+bool
+efi_fdt_overlay_is_compatible(void *dtbo)
+{
+ const int system_root = fdt_path_offset(fdt_data, "/");
+ const int overlay_root = fdt_path_offset(dtbo, "/");
+
+ if (system_root < 0 || overlay_root < 0)
+ return false;
+
+ const int system_ncompat = fdt_stringlist_count(fdt_data, system_root,
+ "compatible");
+ const int overlay_ncompat = fdt_stringlist_count(dtbo, overlay_root,
+ "compatible");
+
+ if (system_ncompat <= 0 || overlay_ncompat <= 0)
+ return false;
+
+ const char *system_compatible, *overlay_compatible;
+ int si, oi;
+
+ for (si = 0; si < system_ncompat; si++) {
+ system_compatible = fdt_stringlist_get(fdt_data,
+ system_root, "compatible", si, NULL);
+ if (system_compatible == NULL)
+ continue;
+ for (oi = 0; oi < overlay_ncompat; oi++) {
+ overlay_compatible = fdt_stringlist_get(dtbo,
+ overlay_root, "compatible", oi, NULL);
+ if (overlay_compatible == NULL)
+ continue;
+ if (strcmp(system_compatible, overlay_compatible) == 0)
+ return true;
+ }
+ }
+
+ return false;
+}
+
+int
+efi_fdt_overlay_apply(void *dtbo, int *fdterr)
+{
+ int err = fdt_overlay_apply(fdt_data, dtbo);
+ if (fdterr)
+ *fdterr = err;
+ return err == 0 ? 0 : EIO;
+}
+
void
efi_fdt_init(u_long addr, u_long len)
{
Index: src/sys/stand/efiboot/efifdt.h
diff -u src/sys/stand/efiboot/efifdt.h:1.4 src/sys/stand/efiboot/efifdt.h:1.5
--- src/sys/stand/efiboot/efifdt.h:1.4 Sun Sep 9 13:37:54 2018
+++ src/sys/stand/efiboot/efifdt.h Sun Apr 21 22:30:41 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: efifdt.h,v 1.4 2018/09/09 13:37:54 jmcneill Exp $ */
+/* $NetBSD: efifdt.h,v 1.5 2019/04/21 22:30:41 thorpej Exp $ */
/*-
* Copyright (c) 2018 Jared McNeill <[email protected]>
@@ -31,6 +31,8 @@ void efi_fdt_memory_map(void);
int efi_fdt_set_data(void *);
void *efi_fdt_data(void);
int efi_fdt_size(void);
+bool efi_fdt_overlay_is_compatible(void *);
+int efi_fdt_overlay_apply(void *, int *);
void efi_fdt_show(void);
void efi_fdt_bootargs(const char *);
void efi_fdt_initrd(u_long, u_long);