From 7a1d3142411b38b7dd34351892039e53b5d7cf80 Mon Sep 17 00:00:00 2001 From: deraadt Date: Mon, 19 Jun 2017 22:50:50 +0000 Subject: [PATCH] As early as possible, create a link /bsd.booted to the /bsd kernel we presume we booted from. If you boot from another kernel, we cannot help you later with hibernate, sorry -- The kernel does not get a useable filename from the bootblocks. In the bootblocks, detect a live hibernate signature and boot from /bsd.booted instead. with yasuoka, lots of discussion with mlarkin, ok tom --- etc/rc | 3 +- sys/arch/amd64/include/biosvar.h | 3 +- sys/arch/amd64/stand/boot/Makefile | 3 +- sys/arch/amd64/stand/efiboot/Makefile.common | 4 +- sys/arch/amd64/stand/libsa/diskprobe.c | 40 ++++++++++++++++++-- sys/arch/i386/include/biosvar.h | 3 +- sys/arch/i386/stand/boot/Makefile | 3 +- sys/arch/i386/stand/libsa/diskprobe.c | 40 ++++++++++++++++++-- sys/stand/boot/boot.c | 12 +++++- 9 files changed, 97 insertions(+), 14 deletions(-) diff --git a/etc/rc b/etc/rc index 4a1e190bec3..1bdac689767 100644 --- a/etc/rc +++ b/etc/rc @@ -1,4 +1,4 @@ -# $OpenBSD: rc,v 1.502 2017/06/14 21:39:53 rpe Exp $ +# $OpenBSD: rc,v 1.503 2017/06/19 22:50:50 deraadt Exp $ # System startup script run by init on autoboot or after single-user. # Output and error are redirected to console by init, and the console is the @@ -377,6 +377,7 @@ mount -a -t nonfs,vnd # others aren't hurt.) mount -uw / chmod og-rwx /bsd +ln -fh /bsd /bsd.booted rm -f /fastboot diff --git a/sys/arch/amd64/include/biosvar.h b/sys/arch/amd64/include/biosvar.h index 2ffd366b09f..8eaf6055079 100644 --- a/sys/arch/amd64/include/biosvar.h +++ b/sys/arch/amd64/include/biosvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: biosvar.h,v 1.22 2015/08/30 10:05:09 yasuoka Exp $ */ +/* $OpenBSD: biosvar.h,v 1.23 2017/06/19 22:50:50 deraadt Exp $ */ /* * Copyright (c) 1997-1999 Michael Shalayeff @@ -131,6 +131,7 @@ typedef struct _bios_diskinfo { #define BDI_GOODLABEL 0x00000002 /* Had SCSI or ST506/ESDI disklabel */ #define BDI_BADLABEL 0x00000004 /* Had another disklabel */ #define BDI_EL_TORITO 0x00000008 /* 2,048-byte sectors */ +#define BDI_HIBVALID 0x00000010 /* hibernate signiture valid */ #define BDI_PICKED 0x80000000 /* kernel-only: cksum matched */ } __packed bios_diskinfo_t; diff --git a/sys/arch/amd64/stand/boot/Makefile b/sys/arch/amd64/stand/boot/Makefile index ebb431ad01e..aab8a1e2d56 100644 --- a/sys/arch/amd64/stand/boot/Makefile +++ b/sys/arch/amd64/stand/boot/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.37 2017/05/30 22:32:10 naddy Exp $ +# $OpenBSD: Makefile,v 1.38 2017/06/19 22:50:50 deraadt Exp $ COPTS?= MAN?= boot.8 @@ -75,6 +75,7 @@ CPPFLAGS+=-DSOFTRAID .endif CPPFLAGS+=-DBOOTMAGIC=$(BOOTMAGIC) ${DEBUGFLAGS} -DLINKADDR=${LINKADDR} CPPFLAGS+=-DSLOW -DSMALL -DNOBYFOUR -DNO_GZIP -DDYNAMIC_CRC_TABLE +CPPFLAGS+=-DHIBERNATE CPPFLAGS+=-DHEAP_LIMIT=${HEAP_LIMIT} -I${S}/stand/boot #-DCOMPAT_UFS CFLAGS+=-m32 $(SACFLAGS) -D__INTERNAL_LIBSA_CREAD -fno-pie AFLAGS+=${NO_INTEGR_AS} diff --git a/sys/arch/amd64/stand/efiboot/Makefile.common b/sys/arch/amd64/stand/efiboot/Makefile.common index d821e0bc39a..6dc1cdebd4d 100644 --- a/sys/arch/amd64/stand/efiboot/Makefile.common +++ b/sys/arch/amd64/stand/efiboot/Makefile.common @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile.common,v 1.10 2016/09/18 16:34:59 jsing Exp $ +# $OpenBSD: Makefile.common,v 1.11 2017/06/19 22:50:50 deraadt Exp $ S= ${.CURDIR}/../../../../.. SADIR= ${.CURDIR}/../.. @@ -68,7 +68,7 @@ ${PROG}: ${PROG.so} .include CFLAGS+= -Wno-pointer-sign CPPFLAGS+= -DSMALL -DSLOW -DNOBYFOUR -D__INTERNAL_LIBSA_CREAD -CPPFLAGS+= -DHEAP_LIMIT=${EFI_HEAP_LIMIT} +CPPFLAGS+= -DHEAP_LIMIT=${EFI_HEAP_LIMIT} -DHIBERNATE ${PROG.so}: ${OBJS} ${LD} ${LDFLAGS} -o ${.TARGET}.tmp ${OBJS} ${LDADD} diff --git a/sys/arch/amd64/stand/libsa/diskprobe.c b/sys/arch/amd64/stand/libsa/diskprobe.c index ba6f875496e..48dfb619840 100644 --- a/sys/arch/amd64/stand/libsa/diskprobe.c +++ b/sys/arch/amd64/stand/libsa/diskprobe.c @@ -1,4 +1,4 @@ -/* $OpenBSD: diskprobe.c,v 1.17 2016/09/11 15:54:11 jsing Exp $ */ +/* $OpenBSD: diskprobe.c,v 1.18 2017/06/19 22:50:50 deraadt Exp $ */ /* * Copyright (c) 1997 Tobias Weingartner @@ -34,6 +34,7 @@ #include #include #include +#include #include #include @@ -54,6 +55,9 @@ /* Local Prototypes */ static int disksum(int); +static void check_hibernate(struct diskinfo *); + +int bootdev_has_hibernate(void); /* export for loadfile() */ /* List of disk devices we found/probed */ struct disklist_lh disklist; @@ -169,8 +173,9 @@ hardprobe(void) dip->bios_info.checksum = 0; /* just in case */ /* Fill out best we can */ - dip->bios_info.bsd_dev = + dip->bsddev = dip->bios_info.bsd_dev = MAKEBOOTDEV(type, 0, 0, bsdunit, RAW_PART); + check_hibernate(dip); /* Add to queue of disks */ TAILQ_INSERT_TAIL(&disklist, dip, list); @@ -224,8 +229,9 @@ efi_hardprobe(void) dip->bios_info.checksum = 0; /* just in case */ /* Fill out best we can */ - dip->bios_info.bsd_dev = + dip->bsddev = dip->bios_info.bsd_dev = MAKEBOOTDEV(type, 0, 0, bsdunit, RAW_PART); + check_hibernate(dip); /* Add to queue of disks */ TAILQ_INSERT_TAIL(&disklist, dip, list); @@ -459,3 +465,31 @@ disksum(int blk) return reprobe; } + +int +bootdev_has_hibernate(void) +{ + return ((bootdev_dip->bios_info.flags & BDI_HIBVALID)? 1 : 0); +} + +static void +check_hibernate(struct diskinfo *dip) +{ + daddr_t sec; + int error; + union hibernate_info hib; + + /* read hibernate */ + if (dip->disklabel.d_partitions[1].p_fstype != FS_SWAP || + DL_GETPSIZE(&dip->disklabel.d_partitions[1]) == 0) + return; + + sec = DL_GETPOFFSET(&dip->disklabel.d_partitions[1]) + + DL_GETPSIZE(&dip->disklabel.d_partitions[1]) - + (sizeof(union hibernate_info) / DEV_BSIZE); + + error = dip->strategy(dip, F_READ, (daddr32_t)sec, sizeof hib, &hib, NULL); + if (error == 0 && hib.magic == HIBERNATE_MAGIC) /* Hibernate present */ + dip->bios_info.flags |= BDI_HIBVALID; + printf("&"); +} diff --git a/sys/arch/i386/include/biosvar.h b/sys/arch/i386/include/biosvar.h index f51b2d020b5..2811c942d25 100644 --- a/sys/arch/i386/include/biosvar.h +++ b/sys/arch/i386/include/biosvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: biosvar.h,v 1.64 2015/09/03 15:52:16 deraadt Exp $ */ +/* $OpenBSD: biosvar.h,v 1.65 2017/06/19 22:50:50 deraadt Exp $ */ /* * Copyright (c) 1997-1999 Michael Shalayeff @@ -161,6 +161,7 @@ typedef struct _bios_diskinfo { #define BDI_GOODLABEL 0x00000002 /* Had SCSI or ST506/ESDI disklabel */ #define BDI_BADLABEL 0x00000004 /* Had another disklabel */ #define BDI_EL_TORITO 0x00000008 /* 2,048-byte sectors */ +#define BDI_HIBVALID 0x00000010 /* hibernate signiture valid */ #define BDI_PICKED 0x80000000 /* kernel-only: cksum matched */ } __packed bios_diskinfo_t; diff --git a/sys/arch/i386/stand/boot/Makefile b/sys/arch/i386/stand/boot/Makefile index 52b440ebc40..82dc91f310c 100644 --- a/sys/arch/i386/stand/boot/Makefile +++ b/sys/arch/i386/stand/boot/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.65 2017/06/01 11:18:53 naddy Exp $ +# $OpenBSD: Makefile,v 1.66 2017/06/19 22:50:50 deraadt Exp $ COPTS?= MAN?= boot.8 @@ -79,6 +79,7 @@ CPPFLAGS+=-DSOFTRAID .endif CPPFLAGS+=-DBOOTMAGIC=$(BOOTMAGIC) ${DEBUGFLAGS} -DLINKADDR=${LINKADDR} CPPFLAGS+=-DSLOW -DSMALL -DNOBYFOUR -DNO_GZIP -DDYNAMIC_CRC_TABLE +CPPFLAGS+=-DHIBERNATE CPPFLAGS+=-DHEAP_LIMIT=${HEAP_LIMIT} -I${S}/stand/boot #-DCOMPAT_UFS CFLAGS+=-m32 $(SACFLAGS) -D__INTERNAL_LIBSA_CREAD -fno-pie AFLAGS+=${NO_INTEGR_AS} diff --git a/sys/arch/i386/stand/libsa/diskprobe.c b/sys/arch/i386/stand/libsa/diskprobe.c index 9b8947cfdfe..2d30b9d859b 100644 --- a/sys/arch/i386/stand/libsa/diskprobe.c +++ b/sys/arch/i386/stand/libsa/diskprobe.c @@ -1,4 +1,4 @@ -/* $OpenBSD: diskprobe.c,v 1.41 2016/09/11 15:54:11 jsing Exp $ */ +/* $OpenBSD: diskprobe.c,v 1.42 2017/06/19 22:50:50 deraadt Exp $ */ /* * Copyright (c) 1997 Tobias Weingartner @@ -34,6 +34,7 @@ #include #include #include +#include #include #include @@ -54,6 +55,9 @@ /* Local Prototypes */ static int disksum(int); +static void check_hibernate(struct diskinfo *); + +int bootdev_has_hibernate(void); /* export for loadfile() */ /* List of disk devices we found/probed */ struct disklist_lh disklist; @@ -169,8 +173,9 @@ hardprobe(void) dip->bios_info.checksum = 0; /* just in case */ /* Fill out best we can */ - dip->bios_info.bsd_dev = + dip->bsddev = dip->bios_info.bsd_dev = MAKEBOOTDEV(type, 0, 0, bsdunit, RAW_PART); + check_hibernate(dip); /* Add to queue of disks */ TAILQ_INSERT_TAIL(&disklist, dip, list); @@ -224,8 +229,9 @@ efi_hardprobe(void) dip->bios_info.checksum = 0; /* just in case */ /* Fill out best we can */ - dip->bios_info.bsd_dev = + dip->bsddev = dip->bios_info.bsd_dev = MAKEBOOTDEV(type, 0, 0, bsdunit, RAW_PART); + check_hibernate(dip); /* Add to queue of disks */ TAILQ_INSERT_TAIL(&disklist, dip, list); @@ -459,3 +465,31 @@ disksum(int blk) return reprobe; } + +int +bootdev_has_hibernate(void) +{ + return ((bootdev_dip->bios_info.flags & BDI_HIBVALID)? 1 : 0); +} + +static void +check_hibernate(struct diskinfo *dip) +{ + daddr_t sec; + int error; + union hibernate_info hib; + + /* read hibernate */ + if (dip->disklabel.d_partitions[1].p_fstype != FS_SWAP || + DL_GETPSIZE(&dip->disklabel.d_partitions[1]) == 0) + return; + + sec = DL_GETPOFFSET(&dip->disklabel.d_partitions[1]) + + DL_GETPSIZE(&dip->disklabel.d_partitions[1]) - + (sizeof(union hibernate_info) / DEV_BSIZE); + + error = dip->strategy(dip, F_READ, (daddr32_t)sec, sizeof hib, &hib, NULL); + if (error == 0 && hib.magic == HIBERNATE_MAGIC) /* Hibernate present */ + dip->bios_info.flags |= BDI_HIBVALID; + printf("&"); +} diff --git a/sys/stand/boot/boot.c b/sys/stand/boot/boot.c index 1365dafa0eb..fc8b0fc3095 100644 --- a/sys/stand/boot/boot.c +++ b/sys/stand/boot/boot.c @@ -1,4 +1,4 @@ -/* $OpenBSD: boot.c,v 1.43 2014/02/19 22:02:15 miod Exp $ */ +/* $OpenBSD: boot.c,v 1.44 2017/06/19 22:50:50 deraadt Exp $ */ /* * Copyright (c) 2003 Dale Rahn @@ -77,6 +77,16 @@ boot(dev_t bootdev) cmd.timeout = boottimeout; st = read_conf(); + +#ifdef HIBERNATE + int bootdev_has_hibernate(void); + + if (bootdev_has_hibernate()) { + strlcpy(cmd.image, "/bsd.booted", sizeof(cmd.image)); + printf("unhibernate detected: switching to %s\n", cmd.image); + } +#endif + if (!bootprompt) snprintf(cmd.path, sizeof cmd.path, "%s:%s", cmd.bootdev, cmd.image); -- 2.20.1