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 <non...@netbsd.org> @@ -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 <jmcne...@invisible.ca> @@ -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 <non...@netbsd.org> @@ -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 <jmcne...@invisible.ca> * 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 <jmcne...@invisible.ca> * 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 <jmcne...@invisible.ca> @@ -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 <jmcne...@invisible.ca> * 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 <jmcne...@invisible.ca> @@ -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);