Date: Thu, 24 Oct 2019 02:43:38 +0000 (UTC) From: Kyle Evans <kevans@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-12@freebsd.org Subject: svn commit: r353979 - in stable/12/stand/efi: boot1 include libefi loader Message-ID: <201910240243.x9O2hcbK093423@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: kevans Date: Thu Oct 24 02:43:38 2019 New Revision: 353979 URL: https://svnweb.freebsd.org/changeset/base/353979 Log: MFC r346345-r346346, r346353, r346407-r346409, r346430, r346573, r346575 r346345: Add a more generic efi_setenv function. efi_setenv allows any UEFI variable to be set. r346346: Add efi_delenv Add an interface to remove / delete UEFI variables. r346353: Minor tweak to the debug Make it clear we're loading from UFS. r346407: Add define for CONST. Newer interfaces take CONST parameters, so define CONST to minimize differences between our headers and the standards docs. r346408: Add UEFI definitions related to converting string to DEVICE_PATH Add definitions from UEFI 2.7 Errata B standards doc for converting a text string to a device path. Added clearly missing 'e' at the end of Device to resolve mismatch in that document in EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL element names. r346409: Add wrapper functions to convert strings to EFI_DEVICE_PATH In anticipation of new functionality, create routines to convert char * and a CHAR16 * to a EFI_DEVICE_PATH EFI_DEVICE_PATH *efi_name_to_devpath(const char *path); EFI_DEVICE_PATH *efi_name_to_devpath16(CHAR16 *path); void efi_devpath_free(EFI_DEVICE_PATH *dp); The first two return an EFI_DEVICE_PATH for the passed in paths. The third frees up the storage the first two return when the caller is done with it. r346430: Start to reduce the number of #ifdef EFI_ZFS_BOOT There's a number of EFI_ZFS_BOOT #ifdefs that aren't needed, or can be eliminated with some trivial #defines. Remove the EFI_ZFS_BOOT ifdefs that aren't needed. Replace libzfs.h include which is not safe to include without EFI_ZFS_BOOT with efizfs.h which is and now conditionally included libzfs.h. Define efizfs_set_preferred away and define efi_zfs_probe to NULL when ZFS is compiled out. r346573: Move setting of console earlier in boot. There's no reason we can't setup the console first thing after the arch flags are setup. We set it undconditionally to efi. This is a good default, and will get us error messages to at least the efi console no matter what. This will also prime the pump so that as other variables are set, they will take effect and the console will be correct as soon as those env vars are set. Also remove the redundant setting of the console to efi when we know the console is efi. r346575: Create boot_img as a global variable Get the information from the image that we're booting and store it in a global variable. Prefer using this to passing it around. Remove the special case for zfs that set the preferred boot handle by having it uses this global variable diretly. Modified: stable/12/stand/efi/boot1/ufs_module.c stable/12/stand/efi/include/efi.h stable/12/stand/efi/include/efidef.h stable/12/stand/efi/include/efidevp.h stable/12/stand/efi/include/efilib.h stable/12/stand/efi/include/efizfs.h stable/12/stand/efi/libefi/devicename.c stable/12/stand/efi/libefi/devpath.c stable/12/stand/efi/libefi/efienv.c stable/12/stand/efi/libefi/efizfs.c stable/12/stand/efi/loader/conf.c stable/12/stand/efi/loader/main.c Directory Properties: stable/12/ (props changed) Modified: stable/12/stand/efi/boot1/ufs_module.c ============================================================================== --- stable/12/stand/efi/boot1/ufs_module.c Thu Oct 24 02:36:42 2019 (r353978) +++ stable/12/stand/efi/boot1/ufs_module.c Thu Oct 24 02:43:38 2019 (r353979) @@ -148,7 +148,7 @@ load(const char *filepath, dev_info_t *dev, void **buf #ifdef EFI_DEBUG { CHAR16 *text = efi_devpath_name(dev->devpath); - DPRINTF("Loading '%s' from %S\n", filepath, text); + DPRINTF("UFS Loading '%s' from %S\n", filepath, text); efi_free_devpath_name(text); } #endif Modified: stable/12/stand/efi/include/efi.h ============================================================================== --- stable/12/stand/efi/include/efi.h Thu Oct 24 02:36:42 2019 (r353978) +++ stable/12/stand/efi/include/efi.h Thu Oct 24 02:43:38 2019 (r353979) @@ -62,6 +62,11 @@ Revision History #include "efiuga.h" /* + * Global variables + */ +extern EFI_LOADED_IMAGE *boot_img; + +/* * FreeBSD UUID */ #define FREEBSD_BOOT_VAR_GUID \ Modified: stable/12/stand/efi/include/efidef.h ============================================================================== --- stable/12/stand/efi/include/efidef.h Thu Oct 24 02:36:42 2019 (r353978) +++ stable/12/stand/efi/include/efidef.h Thu Oct 24 02:43:38 2019 (r353979) @@ -63,6 +63,7 @@ typedef VOID *EFI_EVENT; #define IN #define OUT #define OPTIONAL + #define CONST const #endif Modified: stable/12/stand/efi/include/efidevp.h ============================================================================== --- stable/12/stand/efi/include/efidevp.h Thu Oct 24 02:36:42 2019 (r353978) +++ stable/12/stand/efi/include/efidevp.h Thu Oct 24 02:43:38 2019 (r353979) @@ -433,6 +433,9 @@ typedef union { #define EFI_DEVICE_PATH_TO_TEXT_PROTOCOL_GUID \ { 0x8b843e20, 0x8132, 0x4852, { 0x90, 0xcc, 0x55, 0x1a, 0x4e, 0x4a, 0x7f, 0x1c } } +#define EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL_GUID \ + { 0x05c99a21, 0xc70f, 0x4ad2, { 0x8a, 0x5f, 0x35, 0xdf, 0x33, 0x43, 0xf5, 0x1e } } + INTERFACE_DECL(_EFI_DEVICE_PATH_PROTOCOL); typedef @@ -455,6 +458,23 @@ typedef struct _EFI_DEVICE_PATH_TO_TEXT_PROTOCOL { EFI_DEVICE_PATH_TO_TEXT_NODE ConvertDeviceNodeToText; EFI_DEVICE_PATH_TO_TEXT_PATH ConvertDevicePathToText; } EFI_DEVICE_PATH_TO_TEXT_PROTOCOL; + +typedef +struct _EFI_DEVICE_PATH* +(EFIAPI *EFI_DEVICE_PATH_FROM_TEXT_NODE) ( + IN CONST CHAR16* TextDeviceNode + ); +typedef +struct _EFI_DEVICE_PATH* +(EFIAPI *EFI_DEVICE_PATH_FROM_TEXT_PATH) ( + IN CONST CHAR16* TextDevicePath + ); + + +typedef struct _EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL { + EFI_DEVICE_PATH_FROM_TEXT_NODE ConvertTextToDeviceNode; + EFI_DEVICE_PATH_FROM_TEXT_PATH ConvertTextToDevicePath; +} EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL; #pragma pack() Modified: stable/12/stand/efi/include/efilib.h ============================================================================== --- stable/12/stand/efi/include/efilib.h Thu Oct 24 02:36:42 2019 (r353978) +++ stable/12/stand/efi/include/efilib.h Thu Oct 24 02:43:38 2019 (r353979) @@ -94,6 +94,9 @@ void efi_free_devpath_name(CHAR16 *); EFI_DEVICE_PATH *efi_devpath_to_media_path(EFI_DEVICE_PATH *); UINTN efi_devpath_length(EFI_DEVICE_PATH *); EFI_HANDLE efi_devpath_to_handle(EFI_DEVICE_PATH *path, EFI_HANDLE *handles, unsigned nhandles); +EFI_DEVICE_PATH *efi_name_to_devpath(const char *path); +EFI_DEVICE_PATH *efi_name_to_devpath16(CHAR16 *path); +void efi_devpath_free(EFI_DEVICE_PATH *dp); int efi_status_to_errno(EFI_STATUS); EFI_STATUS errno_to_efi_status(int errno); @@ -124,9 +127,11 @@ void cpy16to8(const CHAR16 *, char *, size_t); * the loader setting / getting FreeBSD specific variables. */ +EFI_STATUS efi_delenv(EFI_GUID *guid, const char *varname); EFI_STATUS efi_freebsd_getenv(const char *v, void *data, __size_t *len); EFI_STATUS efi_getenv(EFI_GUID *g, const char *v, void *data, __size_t *len); EFI_STATUS efi_global_getenv(const char *v, void *data, __size_t *len); +EFI_STATUS efi_setenv(EFI_GUID *guid, const char *varname, UINT32 attr, void *data, __size_t len); EFI_STATUS efi_setenv_freebsd_wcs(const char *varname, CHAR16 *valstr); /* guids and names */ Modified: stable/12/stand/efi/include/efizfs.h ============================================================================== --- stable/12/stand/efi/include/efizfs.h Thu Oct 24 02:36:42 2019 (r353978) +++ stable/12/stand/efi/include/efizfs.h Thu Oct 24 02:43:38 2019 (r353979) @@ -33,6 +33,8 @@ #define _EFIZFS_H_ #ifdef EFI_ZFS_BOOT +#include <libzfs.h> + typedef STAILQ_HEAD(zfsinfo_list, zfsinfo) zfsinfo_list_t; typedef struct zfsinfo @@ -48,8 +50,9 @@ void efi_zfs_probe(void); EFI_HANDLE efizfs_get_handle_by_guid(uint64_t); bool efizfs_get_guid_by_handle(EFI_HANDLE, uint64_t *); zfsinfo_list_t *efizfs_get_zfsinfo_list(void); -void efizfs_set_preferred(EFI_HANDLE); +#else +#define efi_zfs_probe NULL #endif #endif Modified: stable/12/stand/efi/libefi/devicename.c ============================================================================== --- stable/12/stand/efi/libefi/devicename.c Thu Oct 24 02:36:42 2019 (r353978) +++ stable/12/stand/efi/libefi/devicename.c Thu Oct 24 02:43:38 2019 (r353979) @@ -34,12 +34,10 @@ __FBSDID("$FreeBSD$"); #include <sys/param.h> #include <bootstrap.h> #include <disk.h> -#ifdef EFI_ZFS_BOOT -#include <libzfs.h> -#endif #include <efi.h> #include <efilib.h> +#include <efizfs.h> static int efi_parsedev(struct devdesc **, const char *, const char **); Modified: stable/12/stand/efi/libefi/devpath.c ============================================================================== --- stable/12/stand/efi/libefi/devpath.c Thu Oct 24 02:36:42 2019 (r353978) +++ stable/12/stand/efi/libefi/devpath.c Thu Oct 24 02:43:38 2019 (r353979) @@ -29,12 +29,15 @@ __FBSDID("$FreeBSD$"); #include <efi.h> #include <efilib.h> +#include <efichar.h> static EFI_GUID ImageDevicePathGUID = EFI_LOADED_IMAGE_DEVICE_PATH_PROTOCOL_GUID; static EFI_GUID DevicePathGUID = DEVICE_PATH_PROTOCOL; static EFI_GUID DevicePathToTextGUID = EFI_DEVICE_PATH_TO_TEXT_PROTOCOL_GUID; -static EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *textProtocol; +static EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *toTextProtocol; +static EFI_GUID DevicePathFromTextGUID = EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL_GUID; +static EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL *fromTextProtocol; EFI_DEVICE_PATH * efi_lookup_image_devpath(EFI_HANDLE handle) @@ -65,22 +68,20 @@ efi_lookup_devpath(EFI_HANDLE handle) CHAR16 * efi_devpath_name(EFI_DEVICE_PATH *devpath) { - static int once = 1; EFI_STATUS status; if (devpath == NULL) return (NULL); - if (once) { + if (toTextProtocol == NULL) { status = BS->LocateProtocol(&DevicePathToTextGUID, NULL, - (VOID **)&textProtocol); + (VOID **)&toTextProtocol); if (EFI_ERROR(status)) - textProtocol = NULL; - once = 0; + toTextProtocol = NULL; } - if (textProtocol == NULL) + if (toTextProtocol == NULL) return (NULL); - return (textProtocol->ConvertDevicePathToText(devpath, TRUE, TRUE)); + return (toTextProtocol->ConvertDevicePathToText(devpath, TRUE, TRUE)); } void @@ -88,6 +89,46 @@ efi_free_devpath_name(CHAR16 *text) { BS->FreePool(text); +} + +EFI_DEVICE_PATH * +efi_name_to_devpath(const char *path) +{ + EFI_DEVICE_PATH *devpath; + CHAR16 *uv; + size_t ul; + + uv = NULL; + if (utf8_to_ucs2(path, &uv, &ul) != 0) + return (NULL); + devpath = efi_name_to_devpath16(uv); + free(uv); + return (devpath); +} + +EFI_DEVICE_PATH * +efi_name_to_devpath16(CHAR16 *path) +{ + EFI_STATUS status; + + if (path == NULL) + return (NULL); + if (fromTextProtocol == NULL) { + status = BS->LocateProtocol(&DevicePathFromTextGUID, NULL, + (VOID **)&fromTextProtocol); + if (EFI_ERROR(status)) + fromTextProtocol = NULL; + } + if (fromTextProtocol == NULL) + return (NULL); + + return (fromTextProtocol->ConvertTextToDevicePath(path)); +} + +void efi_devpath_free(EFI_DEVICE_PATH *devpath) +{ + + BS->FreePool(devpath); } EFI_DEVICE_PATH * Modified: stable/12/stand/efi/libefi/efienv.c ============================================================================== --- stable/12/stand/efi/libefi/efienv.c Thu Oct 24 02:36:42 2019 (r353978) +++ stable/12/stand/efi/libefi/efienv.c Thu Oct 24 02:43:38 2019 (r353979) @@ -68,7 +68,26 @@ efi_freebsd_getenv(const char *v, void *data, size_t * return (efi_getenv(&FreeBSDBootVarGUID, v, data, len)); } +/* + * efi_setenv -- Sets an env variable. + */ EFI_STATUS +efi_setenv(EFI_GUID *guid, const char *varname, UINT32 attr, void *data, __size_t len) +{ + EFI_STATUS rv; + CHAR16 *uv; + size_t ul; + + uv = NULL; + if (utf8_to_ucs2(varname, &uv, &ul) != 0) + return (EFI_OUT_OF_RESOURCES); + + rv = RS->SetVariable(uv, guid, attr, len, data); + free(uv); + return (rv); +} + +EFI_STATUS efi_setenv_freebsd_wcs(const char *varname, CHAR16 *valstr) { CHAR16 *var = NULL; @@ -84,3 +103,21 @@ efi_setenv_freebsd_wcs(const char *varname, CHAR16 *va return (rv); } +/* + * efi_delenv -- deletes the specified env variable + */ +EFI_STATUS +efi_delenv(EFI_GUID *guid, const char *name) +{ + CHAR16 *var; + size_t len; + EFI_STATUS rv; + + var = NULL; + if (utf8_to_ucs2(name, &var, &len) != 0) + return (EFI_OUT_OF_RESOURCES); + + rv = RS->SetVariable(var, guid, 0, 0, NULL); + free(var); + return rv; +} Modified: stable/12/stand/efi/libefi/efizfs.c ============================================================================== --- stable/12/stand/efi/libefi/efizfs.c Thu Oct 24 02:36:42 2019 (r353978) +++ stable/12/stand/efi/libefi/efizfs.c Thu Oct 24 02:43:38 2019 (r353979) @@ -45,14 +45,6 @@ static zfsinfo_list_t zfsinfo; uint64_t pool_guid; -static EFI_HANDLE preferred; - -void -efizfs_set_preferred(EFI_HANDLE h) -{ - preferred = h; -} - zfsinfo_list_t * efizfs_get_zfsinfo_list(void) { @@ -122,7 +114,7 @@ efi_zfs_probe(void) efipart_hddev.dv_name, hd->pd_unit, pd->pd_unit); if (zfs_probe_dev(devname, &guid) == 0) { insert_zfs(pd->pd_handle, guid); - if (pd->pd_handle == preferred) + if (pd->pd_handle == boot_img->DeviceHandle) pool_guid = guid; } Modified: stable/12/stand/efi/loader/conf.c ============================================================================== --- stable/12/stand/efi/loader/conf.c Thu Oct 24 02:36:42 2019 (r353978) +++ stable/12/stand/efi/loader/conf.c Thu Oct 24 02:43:38 2019 (r353979) @@ -31,9 +31,7 @@ __FBSDID("$FreeBSD$"); #include <bootstrap.h> #include <efi.h> #include <efilib.h> -#ifdef EFI_ZFS_BOOT -#include <libzfs.h> -#endif +#include <efizfs.h> struct devsw *devsw[] = { &efipart_fddev, Modified: stable/12/stand/efi/loader/main.c ============================================================================== --- stable/12/stand/efi/loader/main.c Thu Oct 24 02:36:42 2019 (r353978) +++ stable/12/stand/efi/loader/main.c Thu Oct 24 02:43:38 2019 (r353979) @@ -50,10 +50,7 @@ __FBSDID("$FreeBSD$"); #include <bootstrap.h> #include <smbios.h> -#ifdef EFI_ZFS_BOOT -#include <libzfs.h> #include "efizfs.h" -#endif #include "loader_efi.h" @@ -91,6 +88,11 @@ static int fail_timeout = 5; */ UINT16 boot_current; +/* + * Image that we booted from. + */ +EFI_LOADED_IMAGE *boot_img; + static bool has_keyboard(void) { @@ -303,7 +305,7 @@ fix_dosisms(char *p) enum { BOOT_INFO_OK = 0, BAD_CHOICE = 1, NOT_SPECIFIC = 2 }; static int -match_boot_info(EFI_LOADED_IMAGE *img __unused, char *boot_info, size_t bisz) +match_boot_info(char *boot_info, size_t bisz) { uint32_t attr; uint16_t fplen; @@ -451,7 +453,7 @@ match_boot_info(EFI_LOADED_IMAGE *img __unused, char * * a drop to the OK boot loader prompt is possible. */ static int -find_currdev(EFI_LOADED_IMAGE *img, bool do_bootmgr, bool is_last, +find_currdev(bool do_bootmgr, bool is_last, char *boot_info, size_t boot_info_sz) { pdinfo_t *dp, *pp; @@ -484,7 +486,7 @@ find_currdev(EFI_LOADED_IMAGE *img, bool do_bootmgr, b * loader.conf. */ if (do_bootmgr) { - rv = match_boot_info(img, boot_info, boot_info_sz); + rv = match_boot_info(boot_info, boot_info_sz); switch (rv) { case BOOT_INFO_OK: /* We found it */ return (0); @@ -517,7 +519,7 @@ find_currdev(EFI_LOADED_IMAGE *img, bool do_bootmgr, b * boot protocol to do so. We fail and let UEFI go on to * the next candidate. */ - dp = efiblk_get_pdinfo_by_handle(img->DeviceHandle); + dp = efiblk_get_pdinfo_by_handle(boot_img->DeviceHandle); if (dp != NULL) { text = efi_devpath_name(dp->pd_devpath); if (text != NULL) { @@ -556,7 +558,7 @@ find_currdev(EFI_LOADED_IMAGE *img, bool do_bootmgr, b * any of the nodes in that path match one of the enumerated * handles. Currently, this handle list is only for netboot. */ - if (efi_handle_lookup(img->DeviceHandle, &dev, &unit, &extra) == 0) { + if (efi_handle_lookup(boot_img->DeviceHandle, &dev, &unit, &extra) == 0) { set_currdev_devsw(dev, unit); if (sanity_check_currdev()) return (0); @@ -754,7 +756,6 @@ main(int argc, CHAR16 *argv[]) size_t sz, bosz = 0, bisz = 0; UINT16 boot_order[100]; char boot_info[4096]; - EFI_LOADED_IMAGE *img; char buf[32]; bool uefi_boot_mgr; @@ -763,33 +764,28 @@ main(int argc, CHAR16 *argv[]) archsw.arch_copyin = efi_copyin; archsw.arch_copyout = efi_copyout; archsw.arch_readin = efi_readin; -#ifdef EFI_ZFS_BOOT - /* Note this needs to be set before ZFS init. */ archsw.arch_zfs_probe = efi_zfs_probe; -#endif /* Get our loaded image protocol interface structure. */ - (void) OpenProtocolByHandle(IH, &imgid, (void **)&img); + (void) OpenProtocolByHandle(IH, &imgid, (void **)&boot_img); -#ifdef EFI_ZFS_BOOT - /* Tell ZFS probe code where we booted from */ - efizfs_set_preferred(img->DeviceHandle); -#endif + /* + * Chicken-and-egg problem; we want to have console output early, but + * some console attributes may depend on reading from eg. the boot + * device, which we can't do yet. We can use printf() etc. once this is + * done. So, we set it to the efi console, then call console init. This + * gets us printf early, but also primes the pump for all future console + * changes to take effect, regardless of where they come from. + */ + setenv("console", "efi", 1); + cons_probe(); + /* Init the time source */ efi_time_init(); has_kbd = has_keyboard(); /* - * XXX Chicken-and-egg problem; we want to have console output - * early, but some console attributes may depend on reading from - * eg. the boot device, which we can't do yet. We can use - * printf() etc. once this is done. - */ - setenv("console", "efi", 1); - cons_probe(); - - /* * Initialise the block cache. Set the upper limit. */ bcache_init(32768, 512); @@ -813,17 +809,15 @@ main(int argc, CHAR16 *argv[]) if ((howto & CON_MASK) == 0) { /* No override, uhowto is controlling and efi cons is perfect */ howto = howto | (uhowto & CON_MASK); - setenv("console", "efi", 1); } else if ((howto & CON_MASK) == (uhowto & CON_MASK)) { /* override matches what UEFI told us, efi console is perfect */ - setenv("console", "efi", 1); } else if ((uhowto & (CON_MASK)) != 0) { /* * We detected a serial console on ConOut. All possible * overrides include serial. We can't really override what efi * gives us, so we use it knowing it's the best choice. */ - setenv("console", "efi", 1); + /* Do nothing */ } else { /* * We detected some kind of serial in the override, but ConOut @@ -887,14 +881,14 @@ main(int argc, CHAR16 *argv[]) /* Determine the devpath of our image so we can prefer it. */ - text = efi_devpath_name(img->FilePath); + text = efi_devpath_name(boot_img->FilePath); if (text != NULL) { printf(" Load Path: %S\n", text); efi_setenv_freebsd_wcs("LoaderPath", text); efi_free_devpath_name(text); } - rv = OpenProtocolByHandle(img->DeviceHandle, &devid, (void **)&imgpath); + rv = OpenProtocolByHandle(boot_img->DeviceHandle, &devid, (void **)&imgpath); if (rv == EFI_SUCCESS) { text = efi_devpath_name(imgpath); if (text != NULL) { @@ -981,7 +975,7 @@ main(int argc, CHAR16 *argv[]) * the boot protocol and also allow an escape hatch for users wishing * to try something different. */ - if (find_currdev(img, uefi_boot_mgr, is_last, boot_info, bisz) != 0) + if (find_currdev(uefi_boot_mgr, is_last, boot_info, bisz) != 0) if (!interactive_interrupt("Failed to find bootable partition")) return (EFI_NOT_FOUND);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201910240243.x9O2hcbK093423>