[zfsboot] Fix boot env back compat (#190)

* Fix boot env back compat

zfsboot must try zfsloader before loader in order to remain compatible
with boot environments created prior to zfs functionality being rolled
into loader proper.

* Improve comments in zfsboot

Explain the significance of the load path order, and put the comment
about looping through the paths in the appropriate scope.

Obtained From:  TrueNAS commit 4c60c62fcf0b6b6eac98ee8d46e7bbea64bc86f5
Submitted by: Ryan Moeller <ryan@freqlabs.com>
This commit is contained in:
Warner Losh 2019-06-03 19:10:46 +00:00
parent 4d6afba5e0
commit 63acab6a5b
2 changed files with 28 additions and 8 deletions

View File

@ -33,6 +33,7 @@
#define PATH_CONFIG "/boot/config"
#define PATH_LOADER "/boot/loader"
#define PATH_LOADER_EFI "/boot/loader.efi"
#define PATH_LOADER_ZFS "/boot/zfsloader"
#define PATH_KERNEL "/boot/kernel/kernel"
#endif /* _PATHS_H_ */

View File

@ -87,6 +87,24 @@ static const unsigned char flags[NOPT] = {
};
uint32_t opts;
/*
* Paths to try loading before falling back to the boot2 prompt.
*
* /boot/zfsloader must be tried before /boot/loader in order to remain
* backward compatible with ZFS boot environments where /boot/loader exists
* but does not have ZFS support, which was the case before FreeBSD 12.
*
* If no loader is found, try to load a kernel directly instead.
*/
static const struct string {
const char *p;
size_t len;
} loadpath[] = {
{ PATH_LOADER_ZFS, sizeof(PATH_LOADER_ZFS) },
{ PATH_LOADER, sizeof(PATH_LOADER) },
{ PATH_KERNEL, sizeof(PATH_KERNEL) },
};
static const unsigned char dev_maj[NDEV] = {30, 4, 2};
static char cmd[512];
@ -857,16 +875,17 @@ main(void)
if (nextboot && !autoboot)
reboot();
/*
* Try to exec /boot/loader. If interrupted by a keypress,
* or in case of failure, try to load a kernel directly instead.
*/
if (autoboot && !*kname) {
memcpy(kname, PATH_LOADER, sizeof(PATH_LOADER));
if (!keyhit(3)) {
/*
* Iterate through the list of loader and kernel paths, trying to load.
* If interrupted by a keypress, or in case of failure, drop the user
* to the boot2 prompt.
*/
for (i = 0; i < nitems(loadpath); i++) {
memcpy(kname, loadpath[i].p, loadpath[i].len);
if (keyhit(3))
break;
load();
memcpy(kname, PATH_KERNEL, sizeof(PATH_KERNEL));
}
}