Attachment 'multifix-13.3-RELEASE.diff'

Download

   1 diff --git a/libexec/rc/rc.conf b/libexec/rc/rc.conf
   2 index 824751078833..2846e7f1d144 100644
   3 --- a/libexec/rc/rc.conf
   4 +++ b/libexec/rc/rc.conf
   5 @@ -70,6 +70,10 @@ local_startup="${_localbase}/etc/rc.d" # startup script dirs.
   6  script_name_sep=" "	# Change if your startup scripts' names contain spaces
   7  rc_conf_files="/etc/rc.conf /etc/rc.conf.local"
   8  
   9 +# List of UEFI and kenv(1) variables to synchronize.
  10 +uefivars_variables='LoaderRotate'	   # Space separated list of names of variables
  11 +uefivars_kenv_LoaderRotate='screen.rotate' # List kenv(1) keys, one per UEFI variable
  12 +
  13  # ZFS support
  14  zfs_enable="NO"		# Set to YES to automatically mount ZFS file systems
  15  zfskeys_enable="NO"	# Set YES to autoload ZFS encryption keys
  16 @@ -718,8 +722,12 @@ devfs_set_rulesets=""	# A list of /mount/dev=ruleset_name settings to
  17  devfs_load_rulesets="YES"	# Enable to always load the default rulesets
  18  performance_cx_lowest="NONE"	# Online CPU idle state
  19  performance_cpu_freq="NONE"	# Online CPU frequency
  20 +performance_tz0_active="NONE"	# Online forced active cooling zone
  21 +performance_tz0_PSV="NONE"	# Online passive cooling threshold
  22  economy_cx_lowest="Cmax"	# Offline CPU idle state
  23  economy_cpu_freq="NONE"		# Offline CPU frequency
  24 +economy_tz0_active="NONE"	# Offline forced active cooling zone
  25 +economy_tz0_PSV="NONE"		# Offline passive cooling threshold
  26  virecover_enable="YES"	# Perform housekeeping for the vi(1) editor
  27  ugidfw_enable="NO"	# Load mac_bsdextended(4) rules on boot
  28  bsdextended_script="/etc/rc.bsdextended"	# Default mac_bsdextended(4)
  29 diff --git a/libexec/rc/rc.d/Makefile b/libexec/rc/rc.d/Makefile
  30 index ac35a2b5e28f..bc259c290135 100644
  31 --- a/libexec/rc/rc.d/Makefile
  32 +++ b/libexec/rc/rc.d/Makefile
  33 @@ -201,6 +201,10 @@ BSNMPPACKAGE=	bsnmp
  34  CONFS+=		ccd
  35  .endif
  36  
  37 +.if ${MK_EFI} != "no"
  38 +CONFS+=		uefivars
  39 +.endif
  40 +
  41  .if ${MK_FTP} != "no"
  42  CONFS+=		ftpd
  43  .endif
  44 diff --git a/libexec/rc/rc.d/power_profile b/libexec/rc/rc.d/power_profile
  45 index 71f3f3ad8792..ec07eb920c93 100755
  46 --- a/libexec/rc/rc.d/power_profile
  47 +++ b/libexec/rc/rc.d/power_profile
  48 @@ -79,6 +79,14 @@ case ${state} in
  49  esac
  50  
  51  # Set the various sysctls based on the profile's values.
  52 +node="hw.acpi.thermal.tz0._PSV"
  53 +eval value=\$${profile}_tz0_PSV
  54 +sysctl_set
  55 +
  56 +node="hw.acpi.thermal.tz0.active"
  57 +eval value=\$${profile}_tz0_active
  58 +sysctl_set
  59 +
  60  node="hw.acpi.cpu.cx_lowest"
  61  highest_value="C1"
  62  lowest_value="Cmax"
  63 diff --git a/libexec/rc/rc.d/uefivars b/libexec/rc/rc.d/uefivars
  64 new file mode 100755
  65 index 000000000000..18d20cec7aa1
  66 --- /dev/null
  67 +++ b/libexec/rc/rc.d/uefivars
  68 @@ -0,0 +1,71 @@
  69 +#!/bin/sh
  70 +#
  71 +# Copyright (c) 2003 The FreeBSD Project. All rights reserved.
  72 +#
  73 +# Redistribution and use in source and binary forms, with or without
  74 +# modification, are permitted provided that the following conditions
  75 +# are met:
  76 +# 1. Redistributions of source code must retain the above copyright
  77 +#    notice, this list of conditions and the following disclaimer.
  78 +# 2. Redistributions in binary form must reproduce the above copyright
  79 +#    notice, this list of conditions and the following disclaimer in the
  80 +#    documentation and/or other materials provided with the distribution.
  81 +#
  82 +# THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
  83 +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  84 +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  85 +# ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
  86 +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  87 +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  88 +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  89 +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  90 +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  91 +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  92 +# SUCH DAMAGE.
  93 +#
  94 +# $FreeBSD$
  95 +#
  96 +
  97 +# PROVIDE: uefivars
  98 +# REQUIRE: kld
  99 +# KEYWORD: shutdown
 100 +
 101 +. /etc/rc.subr
 102 +
 103 +name="uefivars"
 104 +desc="Synchronize UEFI with kenv(1) variables"
 105 +start_cmd="uefivars_start"
 106 +stop_cmd="uefivars_start"
 107 +
 108 +efivar="/usr/sbin/efivar -q"
 109 +freebsd_guid='cfee69ad-a0de-47a9-93a8-f63106f8ae99'
 110 +iconv="/usr/bin/iconv -t UCS-2-INTERNAL"
 111 +kenv="/bin/kenv -q"
 112 +
 113 +uefivars_start()
 114 +{
 115 +	local var kenv_key kenv_value UEFI_value
 116 +	for var in $uefivars_variables
 117 +	do
 118 +		eval kenv_key=\$uefivars_kenv_$var
 119 +		kenv_value=`$kenv $kenv_key`
 120 +		if [ -z "$kenv_value" ]
 121 +		then
 122 +			debug "DELETE LoaderRotate"
 123 +			# Delete UEFI variables without corresponding kenv(1) key.
 124 +			$efivar -D ${freebsd_guid}-${var}
 125 +		else
 126 +			# Update UEFI variables that differ from $kenv_value.
 127 +			UEFI_value=`$efivar -p -N -u ${freebsd_guid}-${var}`
 128 +			if [ "$kenv_value" != "$UEFI_value" ]
 129 +			then
 130 +				debug "UPDATE LoaderRotate $config_value"
 131 +				echo -n $kenv_value | $iconv | \
 132 +					$efivar -w ${freebsd_guid}-${var}
 133 +			fi
 134 +		fi
 135 +	done
 136 +}
 137 +
 138 +load_rc_config $name
 139 +run_rc_command "$1"
 140 diff --git a/share/man/man4/acpi_thermal.4 b/share/man/man4/acpi_thermal.4
 141 index 3961ed36276c..256aa978b486 100644
 142 --- a/share/man/man4/acpi_thermal.4
 143 +++ b/share/man/man4/acpi_thermal.4
 144 @@ -22,7 +22,7 @@
 145  .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 146  .\" SUCH DAMAGE.
 147  .\"
 148 -.Dd March 17, 2007
 149 +.Dd July 31, 2022
 150  .Dt ACPI_THERMAL 4
 151  .Os
 152  .Sh NAME
 153 @@ -82,6 +82,9 @@ Current temperature for this zone.
 154  .It Va hw.acpi.thermal.tz%d._PSV
 155  Temperature to start passive cooling by throttling down CPU, etc.
 156  This value can be overridden by the user.
 157 +.It Va hw.acpi.thermal.tz%d._CR3
 158 +Temperature to start critical suspend to RAM (S3).
 159 +This value can be overridden by the user.
 160  .It Va hw.acpi.thermal.tz%d._HOT
 161  Temperature to start critical suspend to disk (S4).
 162  This value can be overridden by the user.
 163 diff --git a/share/man/man4/usb_quirk.4 b/share/man/man4/usb_quirk.4
 164 index 15f5a9718c8f..f199ad56a758 100644
 165 --- a/share/man/man4/usb_quirk.4
 166 +++ b/share/man/man4/usb_quirk.4
 167 @@ -74,6 +74,8 @@ device should be ignored by ums class
 168  does not identify properly
 169  .It UQ_MS_LEADING_BYTE
 170  mouse sends an unknown leading byte
 171 +.It UQ_MS_NO_SETPROTO
 172 +device should not receive "SetProtocol" requests
 173  .It UQ_MS_REVZ
 174  mouse has Z-axis reversed
 175  .It UQ_MS_VENDOR_BTN
 176 diff --git a/share/man/man4/vt.4 b/share/man/man4/vt.4
 177 index c75830bdd44f..f6ba0754fb3f 100644
 178 --- a/share/man/man4/vt.4
 179 +++ b/share/man/man4/vt.4
 180 @@ -356,6 +356,24 @@ To set black and white colors of console palette
 181  .Pp
 182  .Dl kern.vt.color.0.rgb="10,10,10"
 183  .Dl kern.vt.color.15.rgb="#f0f0f0"
 184 +.Pp
 185 +The mode option
 186 +.Sy rotate
 187 +is also supported, with values 0, 90, 180, and 270 representing the degrees
 188 +counterclockwise to rotate the display.  Follow an optional connector name
 189 +and mode with a comma and the mode option.  For example,
 190 +to set the default rotation for all output connectors 90 degrees clockwise:
 191 +.Pp
 192 +.Dl kern.vt.fb.default_mode=",rotate=270"
 193 +.Pp
 194 +This option is only supported by
 195 +.Cm vt_fb
 196 +when it is paired with a KMS video driver, and in most cases the
 197 +.Pp
 198 +.Dl screen.rotate=90
 199 +.Pp
 200 +.Xr loader.conf 5
 201 +setting, which will work with and without KMS, is more appropriate.
 202  .Sh SEE ALSO
 203  .Xr kbdcontrol 1 ,
 204  .Xr login 1 ,
 205 diff --git a/stand/common/gfx_fb.c b/stand/common/gfx_fb.c
 206 index 27ac66f259b1..00e7b77b532c 100644
 207 --- a/stand/common/gfx_fb.c
 208 +++ b/stand/common/gfx_fb.c
 209 @@ -771,6 +771,282 @@ gfxfb_shadow_fill(uint32_t *BltBuffer,
 210  	}
 211  }
 212  
 213 +#if defined(EFI)
 214 +/*
 215 + * Rotate a UEFI Blt buffer of pixels by the specified angle (0,90,180,270) clockwise.
 216 + * Returns NULL if no rotation is performed, or a pointer to a static buffer
 217 + * containing the rotated data.
 218 + * We build the rotated buffer with Delta = 0 since there's no way to know what
 219 + * it should be if the rotation is 90 or 270 degrees.
 220 + */
 221 +static EFI_GRAPHICS_OUTPUT_BLT_PIXEL *
 222 +RotateBuffer(EFI_GRAPHICS_OUTPUT_BLT_PIXEL *inbuf,
 223 +    UINTN angle, UINTN SourceX, UINTN SourceY,
 224 +    UINTN Width, UINTN Height,
 225 +    UINTN Delta)
 226 +{
 227 +	EFI_GRAPHICS_OUTPUT *gop = gfx_state.tg_private;
 228 +	UINTN srcWidth, destOffset, srcOffset;
 229 +	static EFI_GRAPHICS_OUTPUT_BLT_PIXEL *outbuf = NULL;
 230 +
 231 +	if (angle != 90 && angle != 180 && angle != 270)
 232 +		return NULL;
 233 +
 234 +	if (outbuf == NULL &&
 235 +	    (outbuf = malloc(gop->Mode->Info->VerticalResolution *
 236 +	    gop->Mode->Info->HorizontalResolution *
 237 +	    sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL))) == NULL)
 238 +		return NULL;
 239 +
 240 +	srcWidth = Width;
 241 +	if (Delta != 0)
 242 +		srcWidth = Delta;
 243 +
 244 +	/* Check for out-of-bounds access. */
 245 +	if (srcWidth < SourceX + Width ||
 246 +	    srcWidth > gop->Mode->Info->HorizontalResolution ||
 247 +	    SourceX + Width > gop->Mode->Info->HorizontalResolution ||
 248 +	    SourceY + Height > gop->Mode->Info->VerticalResolution)
 249 +		return NULL;
 250 +
 251 +	for (UINTN y = 0; y < Height; y++) {
 252 +		for (UINTN x = 0; x < Width; x++) {
 253 +			srcOffset = (SourceX + x) + (SourceY + y) * srcWidth;
 254 +			switch ((int)angle) {
 255 +			case 0:	/* For reference */
 256 +				destOffset = (SourceX + x) + (SourceY + y) * Width;
 257 +				break;
 258 +			case 90:
 259 +				destOffset = (SourceY + ((Height - 1) - y)) +
 260 +				    (SourceX + x) * Height;
 261 +				break;
 262 +			case 180:
 263 +				destOffset = (SourceX + ((Width - 1) - x)) +
 264 +				    (SourceY + ((Height - 1) - y)) * Width;
 265 +				break;
 266 +			case 270:
 267 +				destOffset = (SourceY + y) +
 268 +				    (SourceX + ((Width - 1) - x)) * Height;
 269 +				break;
 270 +			}
 271 +			outbuf[destOffset] = inbuf[srcOffset];
 272 +		}
 273 +	}
 274 +	return (outbuf);
 275 +}
 276 +
 277 +/* Macros to facilitate rotation. */
 278 +#define SWITCH_VALIDATE
 279 +#ifdef  SWITCH_VALIDATE
 280 +#define	SWITCH(DIR, AXIS, ORIENT, EXTENT)					\
 281 +	if (Panel##DIR##AXIS + Rotated##EXTENT >				\
 282 +	    gop->Mode->Info->ORIENT##Resolution - 1)				\
 283 +		Panel##DIR##AXIS = 0;						\
 284 +	else									\
 285 +		Panel##DIR##AXIS = (gop->Mode->Info->ORIENT##Resolution - 1) -	\
 286 +		    (Panel##DIR##AXIS + Rotated##EXTENT)
 287 +#define	NO_SWITCH(DIR, AXIS, ORIENTATION)					\
 288 +	if (Panel##DIR##AXIS > gop->Mode->Info->ORIENTATION##Resolution - 1)	\
 289 +		Panel##DIR##AXIS = gop->Mode->Info->ORIENTATION##Resolution - 1
 290 +#else
 291 +#define	SWITCH(DIR, AXIS, ORIENT, EXTENT)					\
 292 +	Panel##DIR##AXIS = (gop->Mode->Info->ORIENT##Resolution - 1) -		\
 293 +	    (Panel##DIR##AXIS + Rotated##EXTENT)
 294 +#define	NO_SWITCH(DIR, AXIS, ORIENTATION)
 295 +#endif
 296 +#define SWITCH_SRC_X	SWITCH(Src, X, Horizontal, Width)
 297 +#define SWITCH_DST_X	SWITCH(Dst, X, Horizontal, Width)
 298 +#define	SWITCH_SRC_Y	SWITCH(Src, Y, Vertical, Height)
 299 +#define	SWITCH_DST_Y	SWITCH(Dst, Y, Vertical, Height)
 300 +#define NO_SWITCH_SRC_X	NO_SWITCH(Src, X, Horizontal)
 301 +#define NO_SWITCH_DST_X	NO_SWITCH(Dst, X, Horizontal)
 302 +#define	NO_SWITCH_SRC_Y	NO_SWITCH(Src, Y, Vertical)
 303 +#define	NO_SWITCH_DST_Y	NO_SWITCH(Dst, Y, Vertical)
 304 +
 305 +/*
 306 + * Perhaps better implemented as a separate UEFI gop layer (c.f.
 307 + * https://github.com/apop2/GopRotate), this rotation layer resides in the
 308 + * loader itself, above the UEFI, and will rotate gop->Blt() requests by the
 309 + * specified angle.  It is more complex than a simple rotation because the
 310 + * gop->Blt interface is complex; using the gop direct bitmap interface would be
 311 + * simpler but would require more changes to the loader graphics code.
 312 + */
 313 +EFI_STATUS
 314 +BltRot(EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer,
 315 +    EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,
 316 +    UINTN SourceX, UINTN SourceY,
 317 +    UINTN DestinationX, UINTN DestinationY,
 318 +    UINTN Width, UINTN Height,
 319 +    UINTN Delta)
 320 +{
 321 +	EFI_STATUS status;
 322 +	EFI_GRAPHICS_OUTPUT *gop = gfx_state.tg_private;
 323 +	EFI_GRAPHICS_OUTPUT_BLT_PIXEL *PanelBuffer, *unrotatedBuffer;
 324 +	static EFI_GRAPHICS_OUTPUT_BLT_PIXEL *transformBuffer = NULL;
 325 +	UINTN PanelSrcX, PanelSrcY, PanelDstX, PanelDstY, RotatedWidth, RotatedHeight;
 326 +	UINTN destWidth;
 327 +
 328 +	/*
 329 +	 * Translate logical:
 330 +	 * BltBuffer, SourceX, SourceY, DestinationX, DestinationY, Width, Height
 331 +	 * to physical:
 332 +	 * PanelBuffer, PanelSrcX, PanelSrcY, PanelDstX, PanelDstY, RotatedWidth,
 333 +	 *  RotatedHeight
 334 +	 * corresponding to the display hardware.
 335 +	 *
 336 +	 * Typically DestinationX = 0, DestinationY= 0 will correspond to the upper left
 337 +	 * pixel of the display in its mounted orientation, whereas PanelDstX = 0,
 338 +	 * PanelDstY = 0 will correspond to the hardware panel 0,0 coordinate.
 339 +	 */
 340 +	PanelSrcX = SourceX, PanelSrcY = SourceY;
 341 +	PanelDstX = DestinationX, PanelDstY = DestinationY;
 342 +	RotatedWidth = Width, RotatedHeight = Height;
 343 +	PanelBuffer = BltBuffer;
 344 +
 345 +	switch (BltOperation) {
 346 +	/*
 347 +	 * Not only do we need to rotate the coordinates, we also need to rotate
 348 +	 * the origin of the BltBuffer transfer box (which itself must be
 349 +	 * rotated).
 350 +	 */
 351 +	case EfiBltBufferToVideo:
 352 +		if (rotation == 0 ||
 353 +		    (PanelBuffer = RotateBuffer(BltBuffer, rotation, SourceX, SourceY,
 354 +		    Width, Height, Delta)) == NULL) {
 355 +			PanelBuffer = BltBuffer;
 356 +			break;
 357 +		}
 358 +		Delta = 0;		/* PanelBuffer is built with no delta */
 359 +		/* Fallthrough */
 360 +
 361 +	/* Rotate the coordinates to the panel coordinates. */
 362 +	case EfiBltVideoFill:
 363 +		if (rotation == 90 || rotation == 270) {
 364 +			PanelDstX = DestinationY, PanelDstY = DestinationX;
 365 +			RotatedWidth = Height, RotatedHeight = Width;
 366 +		}
 367 +		switch (rotation) {
 368 +		case 0:
 369 +			break;
 370 +		case 90:
 371 +			SWITCH_DST_X;
 372 +			NO_SWITCH_DST_Y;
 373 +			break;
 374 +		case 180:
 375 +			SWITCH_DST_X;
 376 +			SWITCH_DST_Y;
 377 +			break;
 378 +		case 270:
 379 +			NO_SWITCH_DST_X;
 380 +			SWITCH_DST_Y;
 381 +			break;
 382 +		}
 383 +		break;
 384 +
 385 +	/* Rotate the coordinates to and from the panel coordinates. */
 386 +	case EfiBltVideoToVideo:
 387 +		if (rotation == 90 || rotation == 270) {
 388 +			PanelSrcX = SourceY, PanelSrcY = SourceX;
 389 +			PanelDstX = DestinationY, PanelDstY = DestinationX;
 390 +			RotatedWidth = Height, RotatedHeight = Width;
 391 +		}
 392 +		switch (rotation) {
 393 +		case 90:
 394 +			SWITCH_SRC_X;
 395 +			SWITCH_DST_X;
 396 +			NO_SWITCH_SRC_Y;
 397 +			NO_SWITCH_DST_Y;
 398 +			break;
 399 +		case 180:
 400 +			SWITCH_SRC_X;
 401 +			SWITCH_DST_X;
 402 +			SWITCH_SRC_Y;
 403 +			SWITCH_DST_Y;
 404 +			break;
 405 +		case 270:
 406 +			NO_SWITCH_SRC_X;
 407 +			NO_SWITCH_DST_X;
 408 +			SWITCH_SRC_Y;
 409 +			SWITCH_DST_Y;
 410 +			break;
 411 +		}
 412 +		break;
 413 +	
 414 +	/* Rotate the coordinates from the panel coordinates. */
 415 +	case EfiBltVideoToBltBuffer:
 416 +		if (rotation == 0 ||
 417 +		    (transformBuffer == NULL &&
 418 +		    (transformBuffer = malloc(gop->Mode->Info->HorizontalResolution *
 419 +		    gop->Mode->Info->VerticalResolution *
 420 +		    sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL))) == NULL))
 421 +			break;
 422 +
 423 +		PanelBuffer = transformBuffer;
 424 +		if (rotation == 90 || rotation == 270) {
 425 +			PanelSrcX = SourceY, PanelSrcY = SourceX;
 426 +			RotatedWidth = Height, RotatedHeight = Width;
 427 +		}
 428 +		switch (rotation) {
 429 +		case 90:
 430 +			SWITCH_SRC_X;
 431 +			NO_SWITCH_SRC_Y;
 432 +			break;
 433 +		case 180:
 434 +			SWITCH_SRC_X;
 435 +			SWITCH_SRC_Y;
 436 +			break;
 437 +		case 270:
 438 +			NO_SWITCH_SRC_X;
 439 +			SWITCH_SRC_Y;
 440 +			break;
 441 +		}
 442 +		break;
 443 +	}
 444 +
 445 +	status = gop->Blt(gop, PanelBuffer, BltOperation,
 446 +	    PanelSrcX, PanelSrcY, PanelDstX, PanelDstY,
 447 +	    RotatedWidth, RotatedHeight, Delta);
 448 +	if (EFI_ERROR(status))
 449 +		return (status);
 450 +
 451 +	/* Unless we need to unrotate and merge data into BltBuffer, we are done. */
 452 +	if (BltOperation != EfiBltVideoToBltBuffer || PanelBuffer == BltBuffer)
 453 +		return (status);
 454 +
 455 +	/*
 456 +	 * Until this point, on rotation failure we simply pass the data
 457 +	 * unrotated.  From here on, we return an error (which will likely cause
 458 +	 * loader failure).
 459 +	 */
 460 +	unrotatedBuffer = RotateBuffer(PanelBuffer, 360 - rotation,
 461 +	    DestinationX, DestinationY, Width, Height, Delta);
 462 +	if (unrotatedBuffer == NULL)
 463 +		return (EFI_OUT_OF_RESOURCES);
 464 +
 465 +	/*
 466 +	 * It is not obvious what the correct reconstruction of a non-zero delta
 467 +	 * should be.  This is likely to work correctly.
 468 +	 */
 469 +	destWidth = Width;
 470 +	if (Delta != 0)
 471 +		destWidth = Delta;
 472 +
 473 +	/* Check for out-of-bounds access. */
 474 +	if (destWidth < DestinationX + Width ||
 475 +	    destWidth > gop->Mode->Info->HorizontalResolution ||
 476 +	    DestinationX + Width > gop->Mode->Info->HorizontalResolution ||
 477 +	    DestinationY + Height > gop->Mode->Info->VerticalResolution)
 478 +		return (EFI_INVALID_PARAMETER);
 479 +
 480 +	for (UINTN y = DestinationY; y < DestinationY + Height; y++) {
 481 +		for (UINTN x = DestinationX; x < DestinationX + Width; x++) {
 482 +			BltBuffer[x + y * destWidth] = unrotatedBuffer[x + y * Width];
 483 +		}
 484 +	}
 485 +	return (status);
 486 +}
 487 +#endif
 488 +
 489  int
 490  gfxfb_blt(void *BltBuffer, GFXFB_BLT_OPERATION BltOperation,
 491      uint32_t SourceX, uint32_t SourceY,
 492 @@ -794,28 +1070,26 @@ gfxfb_blt(void *BltBuffer, GFXFB_BLT_OPERATION BltOperation,
 493  		tpl = BS->RaiseTPL(TPL_NOTIFY);
 494  		switch (BltOperation) {
 495  		case GfxFbBltVideoFill:
 496 -			gfxfb_shadow_fill(BltBuffer, DestinationX,
 497 -			    DestinationY, Width, Height);
 498 -			status = gop->Blt(gop, BltBuffer, EfiBltVideoFill,
 499 +			status = BltRot(BltBuffer, EfiBltVideoFill,
 500  			    SourceX, SourceY, DestinationX, DestinationY,
 501  			    Width, Height, Delta);
 502  			break;
 503  
 504  		case GfxFbBltVideoToBltBuffer:
 505 -			status = gop->Blt(gop, BltBuffer,
 506 +			status = BltRot(BltBuffer,
 507  			    EfiBltVideoToBltBuffer,
 508  			    SourceX, SourceY, DestinationX, DestinationY,
 509  			    Width, Height, Delta);
 510  			break;
 511  
 512  		case GfxFbBltBufferToVideo:
 513 -			status = gop->Blt(gop, BltBuffer, EfiBltBufferToVideo,
 514 +			status = BltRot(BltBuffer, EfiBltBufferToVideo,
 515  			    SourceX, SourceY, DestinationX, DestinationY,
 516  			    Width, Height, Delta);
 517  			break;
 518  
 519  		case GfxFbBltVideoToVideo:
 520 -			status = gop->Blt(gop, BltBuffer, EfiBltVideoToVideo,
 521 +			status = BltRot(BltBuffer, EfiBltVideoToVideo,
 522  			    SourceX, SourceY, DestinationX, DestinationY,
 523  			    Width, Height, Delta);
 524  			break;
 525 diff --git a/stand/common/gfx_fb.h b/stand/common/gfx_fb.h
 526 index adb60c673ea9..50bfe0748f8d 100644
 527 --- a/stand/common/gfx_fb.h
 528 +++ b/stand/common/gfx_fb.h
 529 @@ -257,6 +257,9 @@ struct text_pixel {
 530  
 531  extern const int cons_to_vga_colors[NCOLORS];
 532  
 533 +/* Set by freebsd-LoaderRotate UEFI variable, determines rotation of framebuffer. */
 534 +extern uint32_t rotation;
 535 +
 536  /* Screen buffer to track changes on the terminal screen. */
 537  extern struct text_pixel *screen_buffer;
 538  bool is_same_pixel(struct text_pixel *, struct text_pixel *);
 539 diff --git a/stand/defaults/loader.conf.5 b/stand/defaults/loader.conf.5
 540 index bb40df0333cf..7c82dbd3c7f1 100644
 541 --- a/stand/defaults/loader.conf.5
 542 +++ b/stand/defaults/loader.conf.5
 543 @@ -306,6 +306,16 @@ If EDID is not available, the default resolution is 800x600 (if available).
 544  .Va screen.width ,
 545  .Va screen.depth
 546  are set by loader when loader is using framebuffer mode to draw the screen.
 547 +.It Va screen.rotate
 548 +Sets the rotation of the framebuffer console to 0, 90, 180, or 270 degrees clockwise.
 549 +If KMS is present, the rotation may be performed in hardware,
 550 +and an additional value, "AUTO", is supported which will often detect the
 551 +correct rotation.
 552 +.Pp
 553 +This option will also rotate the screen of the EFI boot loader; because the rotation
 554 +setting for the EFI loader is stored in the EFI itself during shutdown based upon the
 555 +value present in the current kernel environment,
 556 +it will take a second reboot to pass a change to the loader.
 557  .It Va efi_max_resolution
 558  .It Va vbe_max_resolution
 559  Specify the maximum desired resolution for the EFI or VBE framebuffer console.
 560 diff --git a/stand/efi/libefi/env.c b/stand/efi/libefi/env.c
 561 index 6887038fe950..a495580de17d 100644
 562 --- a/stand/efi/libefi/env.c
 563 +++ b/stand/efi/libefi/env.c
 564 @@ -467,7 +467,7 @@ efi_print_mem_type(const CHAR16 *varnamearg __unused, uint8_t *data,
 565  
 566  /*
 567   * Print FreeBSD variables.
 568 - * We have LoaderPath and LoaderDev as CHAR16 strings.
 569 + * We have LoaderRotate, LoaderPath and LoaderDev as CHAR16 strings.
 570   */
 571  static int
 572  efi_print_freebsd(const CHAR16 *varnamearg, uint8_t *data,
 573 @@ -479,7 +479,8 @@ efi_print_freebsd(const CHAR16 *varnamearg, uint8_t *data,
 574  	if (ucs2_to_utf8(varnamearg, &var) != 0)
 575  		return (CMD_ERROR);
 576  
 577 -	if (strcmp("LoaderPath", var) == 0 ||
 578 +	if (strcmp("LoaderRotate", var) == 0 ||
 579 +	    strcmp("LoaderPath", var) == 0 ||
 580  	    strcmp("LoaderDev", var) == 0) {
 581  		printf(" = ");
 582  		printf("%S", (CHAR16 *)data);
 583 diff --git a/stand/efi/loader/bootinfo.c b/stand/efi/loader/bootinfo.c
 584 index 1f3664b50948..df004d8808f2 100644
 585 --- a/stand/efi/loader/bootinfo.c
 586 +++ b/stand/efi/loader/bootinfo.c
 587 @@ -184,8 +184,17 @@ bi_load_efi_data(struct preloaded_file *kfp, bool exit_bs)
 588  
 589  	efifb.fb_addr = gfx_state.tg_fb.fb_addr;
 590  	efifb.fb_size = gfx_state.tg_fb.fb_size;
 591 -	efifb.fb_height = gfx_state.tg_fb.fb_height;
 592 -	efifb.fb_width = gfx_state.tg_fb.fb_width;
 593 +	/*
 594 +	 * If we have rotated the framebuffer height and width, rotate them back
 595 +	 * before passing them to the kernel
 596 +	 */
 597 +	if (rotation == 90 || rotation == 270) {
 598 +	    efifb.fb_height = gfx_state.tg_fb.fb_width;
 599 +	    efifb.fb_width = gfx_state.tg_fb.fb_height;
 600 +	} else {
 601 +	    efifb.fb_height = gfx_state.tg_fb.fb_height;
 602 +	    efifb.fb_width = gfx_state.tg_fb.fb_width;
 603 +	}
 604  	efifb.fb_stride = gfx_state.tg_fb.fb_stride;
 605  	efifb.fb_mask_red = gfx_state.tg_fb.fb_mask_red;
 606  	efifb.fb_mask_green = gfx_state.tg_fb.fb_mask_green;
 607 @@ -327,6 +336,7 @@ bi_load(char *args, vm_offset_t *modulep, vm_offset_t *kernendp, bool exit_bs)
 608  	vm_offset_t size;
 609  	char *rootdevname;
 610  	int howto;
 611 +	char *autorotate, strbuf[4];
 612  	bool is64 = sizeof(long) == 8;
 613  #if defined(LOADER_FDT_SUPPORT)
 614  	vm_offset_t dtbp;
 615 @@ -349,6 +359,17 @@ bi_load(char *args, vm_offset_t *modulep, vm_offset_t *kernendp, bool exit_bs)
 616  #endif
 617  	howto = bi_getboothowto(args);
 618  
 619 +	/*
 620 +	 * If screen.rotate="AUTO", pass the current rotation to the kernel to
 621 +	 * use until the autodetection completes.
 622 +	 */
 623 +	if (rotation != 0 &&
 624 +	    (autorotate = getenv("screen.rotate")) != NULL &&
 625 +	    strncasecmp(autorotate, "auto", 5) == 0) {
 626 +		snprintf(strbuf, sizeof(strbuf), "%d", rotation);
 627 +		setenv("screen.autorotate", strbuf, 1);
 628 +	}
 629 +
 630  	/*
 631  	 * Allow the environment variable 'rootdev' to override the supplied
 632  	 * device. This should perhaps go to MI code and/or have $rootdev
 633 diff --git a/stand/efi/loader/framebuffer.c b/stand/efi/loader/framebuffer.c
 634 index 56693187b576..6be3d384e741 100644
 635 --- a/stand/efi/loader/framebuffer.c
 636 +++ b/stand/efi/loader/framebuffer.c
 637 @@ -40,7 +40,9 @@
 638  #include <machine/metadata.h>
 639  
 640  #include "bootstrap.h"
 641 +#include "efichar.h"
 642  #include "framebuffer.h"
 643 +#include "gfx_fb.h"
 644  
 645  static EFI_GUID conout_guid = EFI_CONSOLE_OUT_DEVICE_GUID;
 646  EFI_GUID gop_guid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
 647 @@ -53,6 +55,9 @@ static EFI_HANDLE gop_handle;
 648  /* Cached EDID. */
 649  struct vesa_edid_info *edid_info = NULL;
 650  
 651 +/* Angle to rotate boot console display. */
 652 +uint32_t rotation = 0;
 653 +
 654  static EFI_GRAPHICS_OUTPUT *gop;
 655  static EFI_UGA_DRAW_PROTOCOL *uga;
 656  
 657 @@ -149,11 +154,42 @@ efifb_from_gop(struct efi_fb *efifb, EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *mode,
 658      EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *info)
 659  {
 660  	int result;
 661 +	size_t len = 0;
 662 +	efi_char *buf;
 663 +	char *angle = NULL;
 664 +	EFI_STATUS rv;
 665 +
 666 +	/*
 667 +	 * Use the UEFI variable freebsd-LoaderRotate to rotate the framebuffer
 668 +	 * to match the panel orientation.  We use a UEFI variable because
 669 +	 * the framebuffer is set up very early in the boot process, before
 670 +	 * loader variables (even the early /boot/efi/EFI/FreeBSD/loader.env
 671 +	 * variables) are set up.
 672 +	 *
 673 +	 * It is intended that an rc.d script shall use the screen.rotate loader
 674 +	 * variable to update freebsd-LoaderRotate for the next boot.
 675 +	 */
 676 +	if (efi_freebsd_getenv("LoaderRotate", NULL, &len) == EFI_BUFFER_TOO_SMALL)
 677 +	    if ((buf = calloc(len + 1, sizeof(efi_char)))) {
 678 +		if (efi_freebsd_getenv("LoaderRotate", buf, &len) == EFI_SUCCESS)
 679 +		    if (ucs2_to_utf8(buf, &angle) == 0) {
 680 +			rotation = strtol(angle, NULL, 0);
 681 +			free(angle);
 682 +		    }
 683 +		free(buf);
 684 +	    }
 685 +	if (rotation != 90 && rotation != 180 && rotation != 270)
 686 +	    rotation = 0;
 687  
 688  	efifb->fb_addr = mode->FrameBufferBase;
 689  	efifb->fb_size = mode->FrameBufferSize;
 690 -	efifb->fb_height = info->VerticalResolution;
 691 -	efifb->fb_width = info->HorizontalResolution;
 692 +	if (rotation == 90 || rotation == 270) {
 693 +	    efifb->fb_width = info->VerticalResolution;
 694 +	    efifb->fb_height = info->HorizontalResolution;
 695 +	} else {
 696 +	    efifb->fb_height = info->VerticalResolution;
 697 +	    efifb->fb_width = info->HorizontalResolution;
 698 +	}
 699  	efifb->fb_stride = info->PixelsPerScanLine;
 700  	result = efifb_mask_from_pixfmt(efifb, info->PixelFormat,
 701  	    &info->PixelInformation);
 702 diff --git a/stand/lua/config.lua b/stand/lua/config.lua
 703 index 2f22056efde2..b235553b061e 100644
 704 --- a/stand/lua/config.lua
 705 +++ b/stand/lua/config.lua
 706 @@ -64,7 +64,7 @@ local MSG_FAILSYN_BADVAR = "Malformed variable expression at position '%d'"
 707  -- env_var entries in the pattern table.  This is perhaps a good target for a
 708  -- little refactoring.
 709  local MODULEEXPR = '([%w%d-_.]+)'
 710 -local QVALEXPR = '"(.*)"'
 711 +local QVALEXPR = '"([^"]*)"'
 712  local QVALREPL = QVALEXPR:gsub('%%', '%%%%')
 713  local WORDEXPR = "([-%w%d][-%w%d_.]*)"
 714  local WORDREPL = WORDEXPR:gsub('%%', '%%%%')
 715 diff --git a/sys/dev/acpica/acpi_thermal.c b/sys/dev/acpica/acpi_thermal.c
 716 index c436390d84b4..fb7a478fd479 100644
 717 --- a/sys/dev/acpica/acpi_thermal.c
 718 +++ b/sys/dev/acpica/acpi_thermal.c
 719 @@ -58,7 +58,7 @@ ACPI_MODULE_NAME("THERMAL")
 720  #define TZ_NOTIFY_TEMPERATURE	0x80 /* Temperature changed. */
 721  #define TZ_NOTIFY_LEVELS	0x81 /* Cooling levels changed. */
 722  #define TZ_NOTIFY_DEVICES	0x82 /* Device lists changed. */
 723 -#define TZ_NOTIFY_CRITICAL	0xcc /* Fake notify that _CRT/_HOT reached. */
 724 +#define TZ_NOTIFY_CRITICAL	0xcc /* Fake notify that _CRT/_HOT/_CR3 reached. */
 725  
 726  /* Check for temperature changes every 10 seconds by default */
 727  #define TZ_POLLRATE	10
 728 @@ -76,6 +76,7 @@ struct acpi_tz_zone {
 729      ACPI_BUFFER	al[TZ_NUMLEVELS];
 730      int		crt;
 731      int		hot;
 732 +    int		cr3;
 733      ACPI_BUFFER	psl;
 734      int		psv;
 735      int		tc1;
 736 @@ -95,8 +96,9 @@ struct acpi_tz_softc {
 737      int				tz_thflags;	/*Current temp-related flags*/
 738  #define TZ_THFLAG_NONE		0
 739  #define TZ_THFLAG_PSV		(1<<0)
 740 -#define TZ_THFLAG_HOT		(1<<2)
 741 -#define TZ_THFLAG_CRT		(1<<3)
 742 +#define TZ_THFLAG_CR3		(1<<2)
 743 +#define TZ_THFLAG_HOT		(1<<3)
 744 +#define TZ_THFLAG_CRT		(1<<4)
 745      int				tz_flags;
 746  #define TZ_FLAG_NO_SCP		(1<<0)		/*No _SCP method*/
 747  #define TZ_FLAG_GETPROFILE	(1<<1)		/*Get power_profile in timeout*/
 748 @@ -280,6 +282,10 @@ acpi_tz_attach(device_t dev)
 749          OID_AUTO, "_PSV", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, sc,
 750  	offsetof(struct acpi_tz_softc, tz_zone.psv), acpi_tz_temp_sysctl, "IK",
 751  	"passive cooling temp setpoint");
 752 +    SYSCTL_ADD_PROC(&sc->tz_sysctl_ctx, SYSCTL_CHILDREN(sc->tz_sysctl_tree),
 753 +        OID_AUTO, "_CR3", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, sc,
 754 +	offsetof(struct acpi_tz_softc, tz_zone.cr3), acpi_tz_temp_sysctl, "IK",
 755 +	"too warm temp setpoint (standby now)");
 756      SYSCTL_ADD_PROC(&sc->tz_sysctl_ctx, SYSCTL_CHILDREN(sc->tz_sysctl_tree),
 757          OID_AUTO, "_HOT", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, sc,
 758  	offsetof(struct acpi_tz_softc, tz_zone.hot), acpi_tz_temp_sysctl, "IK",
 759 @@ -419,6 +425,7 @@ acpi_tz_establish(struct acpi_tz_softc *sc)
 760      }
 761      acpi_tz_getparam(sc, "_CRT", &sc->tz_zone.crt);
 762      acpi_tz_getparam(sc, "_HOT", &sc->tz_zone.hot);
 763 +    acpi_tz_getparam(sc, "_CR3", &sc->tz_zone.cr3);
 764      sc->tz_zone.psl.Length = ACPI_ALLOCATE_BUFFER;
 765      sc->tz_zone.psl.Pointer = NULL;
 766      AcpiEvaluateObject(sc->tz_handle, "_PSL", NULL, &sc->tz_zone.psl);
 767 @@ -436,6 +443,7 @@ acpi_tz_establish(struct acpi_tz_softc *sc)
 768       */
 769      acpi_tz_sanity(sc, &sc->tz_zone.crt, "_CRT");
 770      acpi_tz_sanity(sc, &sc->tz_zone.hot, "_HOT");
 771 +    acpi_tz_sanity(sc, &sc->tz_zone.cr3, "_CR3");
 772      acpi_tz_sanity(sc, &sc->tz_zone.psv, "_PSV");
 773      for (i = 0; i < TZ_NUMLEVELS; i++)
 774  	acpi_tz_sanity(sc, &sc->tz_zone.ac[i], "_ACx");
 775 @@ -493,6 +501,7 @@ acpi_tz_get_temperature(struct acpi_tz_softc *sc)
 776  static void
 777  acpi_tz_monitor(void *Context)
 778  {
 779 +    struct acpi_softc	 *acpi_sc;
 780      struct acpi_tz_softc *sc;
 781      struct	timespec curtime;
 782      int		temp;
 783 @@ -543,6 +552,8 @@ acpi_tz_monitor(void *Context)
 784      newflags = TZ_THFLAG_NONE;
 785      if (sc->tz_zone.psv != -1 && temp >= sc->tz_zone.psv)
 786  	newflags |= TZ_THFLAG_PSV;
 787 +    if (sc->tz_zone.cr3 != -1 && temp >= sc->tz_zone.cr3)
 788 +	newflags |= TZ_THFLAG_CR3;
 789      if (sc->tz_zone.hot != -1 && temp >= sc->tz_zone.hot)
 790  	newflags |= TZ_THFLAG_HOT;
 791      if (sc->tz_zone.crt != -1 && temp >= sc->tz_zone.crt)
 792 @@ -593,7 +604,7 @@ acpi_tz_monitor(void *Context)
 793      /* XXX (de)activate any passive cooling that may be required. */
 794  
 795      /*
 796 -     * If the temperature is at _HOT or _CRT, increment our event count.
 797 +     * If the temperature is at _CR3, _HOT or _CRT, increment our event count.
 798       * If it has occurred enough times, shutdown the system.  This is
 799       * needed because some systems will report an invalid high temperature
 800       * for one poll cycle.  It is suspected this is due to the embedded
 801 @@ -602,13 +613,18 @@ acpi_tz_monitor(void *Context)
 802       *
 803       * If we're almost at that threshold, notify the user through devd(8).
 804       */
 805 -    if ((newflags & (TZ_THFLAG_HOT | TZ_THFLAG_CRT)) != 0) {
 806 +    if ((newflags & (TZ_THFLAG_CR3 | TZ_THFLAG_HOT | TZ_THFLAG_CRT)) != 0) {
 807  	sc->tz_validchecks++;
 808  	if (sc->tz_validchecks == TZ_VALIDCHECKS) {
 809  	    device_printf(sc->tz_dev,
 810  		"WARNING - current temperature (%d.%dC) exceeds safe limits\n",
 811  		TZ_KELVTOC(sc->tz_temperature));
 812 -	    shutdown_nice(RB_POWEROFF);
 813 +	    if ((newflags & (TZ_THFLAG_HOT | TZ_THFLAG_CRT)) != 0)
 814 +		shutdown_nice(RB_POWEROFF);
 815 +	    else {
 816 +		acpi_sc = acpi_device_get_parent_softc(sc->tz_dev);
 817 +		acpi_ReqSleepState(acpi_sc, ACPI_STATE_S3);
 818 +	    }
 819  	} else if (sc->tz_validchecks == TZ_NOTIFYCOUNT)
 820  	    acpi_UserNotify("Thermal", sc->tz_handle, TZ_NOTIFY_CRITICAL);
 821      } else {
 822 @@ -1004,51 +1020,68 @@ acpi_tz_thread(void *arg)
 823  static int
 824  acpi_tz_cpufreq_restore(struct acpi_tz_softc *sc)
 825  {
 826 -    device_t dev;
 827 -    int error;
 828 +    device_t *devs;
 829 +    int devcount, error, n;
 830  
 831      if (!sc->tz_cooling_updated)
 832  	return (0);
 833 -    if ((dev = devclass_get_device(devclass_find("cpufreq"), 0)) == NULL)
 834 +
 835 +    if ((error = devclass_get_devices(devclass_find("cpufreq"), &devs, &devcount))) {
 836 +	free(devs, M_TEMP);
 837  	return (ENXIO);
 838 +    }
 839 +
 840      ACPI_VPRINT(sc->tz_dev, acpi_device_get_parent_softc(sc->tz_dev),
 841  	"temperature %d.%dC: resuming previous clock speed (%d MHz)\n",
 842  	TZ_KELVTOC(sc->tz_temperature), sc->tz_cooling_saved_freq);
 843 -    error = CPUFREQ_SET(dev, NULL, CPUFREQ_PRIO_KERN);
 844 +    for (n = 0; n < devcount; n++) {
 845 +	if ((error = CPUFREQ_SET(devs[n], NULL, CPUFREQ_PRIO_KERN))) {
 846 +	    /*
 847 +	     * If you find yourself here:  cf_set_method() in kern_cpu.c
 848 +	     * requires CPUFREQ_GET() be run before CPUFREQ_SET(), otherwise on
 849 +	     * a restore sc->curr_level.total_set.freq = CPUFREQ_VAL_UNKNOWN,
 850 +	     * and then if it hasn't been updated the next save/restore will fail.
 851 +	     */
 852 +	    device_printf(sc->tz_dev, "cpu%d: failed to restore cpufreq priority\n", n);
 853 +	    break;
 854 +	}
 855 +    }
 856      if (error == 0)
 857  	sc->tz_cooling_updated = FALSE;
 858 +
 859 +    free(devs, M_TEMP);
 860      return (error);
 861  }
 862  
 863  static int
 864  acpi_tz_cpufreq_update(struct acpi_tz_softc *sc, int req)
 865  {
 866 -    device_t dev;
 867 +    device_t *devs;
 868      struct cf_level *levels;
 869 -    int num_levels, error, freq, desired_freq, perf, i;
 870 +    int num_levels, error, freq, desired_freq, perf, devcount, i, n;
 871  
 872      levels = malloc(CPUFREQ_MAX_LEVELS * sizeof(*levels), M_TEMP, M_NOWAIT);
 873      if (levels == NULL)
 874  	return (ENOMEM);
 875  
 876      /*
 877 -     * Find the main device, cpufreq0.  We don't yet support independent
 878 -     * CPU frequency control on SMP.
 879 +     * Find the main device, cpufreq0.  We make plans based upon cpu0, and
 880 +     * change all the cpu frequencies to the same level.
 881       */
 882 -    if ((dev = devclass_get_device(devclass_find("cpufreq"), 0)) == NULL) {
 883 -	error = ENXIO;
 884 +    if ((error = devclass_get_devices(devclass_find("cpufreq"), &devs, &devcount))) {
 885 +	free(devs, M_TEMP);
 886  	goto out;
 887      }
 888  
 889 -    /* Get the current frequency. */
 890 -    error = CPUFREQ_GET(dev, &levels[0]);
 891 +    /* Get the current frequency for cpu0. */
 892 +    error = CPUFREQ_GET(devs[0], &levels[0]);
 893      if (error)
 894  	goto out;
 895      freq = levels[0].total_set.freq;
 896  
 897 -    /* Get the current available frequency levels. */
 898 +    /* Get the current available frequency levels for cpu0. */
 899      num_levels = CPUFREQ_MAX_LEVELS;
 900 -    error = CPUFREQ_LEVELS(dev, levels, &num_levels);
 901 +    error = CPUFREQ_LEVELS(devs[0], levels, &num_levels);
 902      if (error) {
 903  	if (error == E2BIG)
 904  	    printf("cpufreq: need to increase CPUFREQ_MAX_LEVELS\n");
 905 @@ -1109,8 +1142,22 @@ acpi_tz_cpufreq_update(struct acpi_tz_softc *sc, int req)
 906  	    TZ_KELVTOC(sc->tz_temperature),
 907  	    (freq > levels[i].total_set.freq) ? "de" : "in",
 908  	    freq, levels[i].total_set.freq);
 909 -	error = CPUFREQ_SET(dev, &levels[i], CPUFREQ_PRIO_KERN);
 910 -	if (error == 0 && !sc->tz_cooling_updated) {
 911 +
 912 +	/* Change all the cpus to the chosen frequency. */
 913 +	for (n = 0; n < devcount; n++) {
 914 +	    /* CPUFREQ_SET() fails occasionally without this. */
 915 +	    if ((error = CPUFREQ_GET(devs[n], &levels[0])))
 916 +		goto out;
 917 +
 918 +	    if ((error = CPUFREQ_LEVELS(devs[n], levels, &num_levels))) {
 919 +		if (error == E2BIG)
 920 +		    printf("cpufreq: need to increase CPUFREQ_MAX_LEVELS\n");
 921 +		goto out;
 922 +	    }
 923 +	    if ((error = CPUFREQ_SET(devs[n], &levels[i], CPUFREQ_PRIO_KERN)))
 924 +		goto out;
 925 +	}
 926 +	if (!sc->tz_cooling_updated) {
 927  	    sc->tz_cooling_saved_freq = freq;
 928  	    sc->tz_cooling_updated = TRUE;
 929  	}
 930 @@ -1119,6 +1166,7 @@ acpi_tz_cpufreq_update(struct acpi_tz_softc *sc, int req)
 931  out:
 932      if (levels)
 933  	free(levels, M_TEMP);
 934 +    free(devs, M_TEMP);
 935      return (error);
 936  }
 937  
 938 diff --git a/sys/dev/usb/input/ukbd.c b/sys/dev/usb/input/ukbd.c
 939 index 4eac1b546b4d..88c95ad04ef5 100644
 940 --- a/sys/dev/usb/input/ukbd.c
 941 +++ b/sys/dev/usb/input/ukbd.c
 942 @@ -962,7 +962,8 @@ ukbd_probe(device_t dev)
 943  		return (ENXIO);
 944  
 945  	if (hid_is_keyboard(d_ptr, d_len)) {
 946 -		if (hid_is_mouse(d_ptr, d_len)) {
 947 +		if (hid_is_mouse(d_ptr, d_len) &&
 948 +		    !usb_test_quirk(uaa, UQ_UMS_IGNORE)) {
 949  			/*
 950  			 * NOTE: We currently don't support USB mouse
 951  			 * and USB keyboard on the same USB endpoint.
 952 diff --git a/sys/dev/usb/input/ums.c b/sys/dev/usb/input/ums.c
 953 index d8dc2e8f19c3..1dbf4446b14f 100644
 954 --- a/sys/dev/usb/input/ums.c
 955 +++ b/sys/dev/usb/input/ums.c
 956 @@ -590,13 +590,15 @@ ums_attach(device_t dev)
 957  	usb_callout_init_mtx(&sc->sc_callout, &sc->sc_mtx, 0);
 958  
 959  	/*
 960 -         * Force the report (non-boot) protocol.
 961 +         * Force the report (non-boot) protocol unless
 962 +         * UQ_MS_NO_SETPROTO is set.
 963           *
 964           * Mice without boot protocol support may choose not to implement
 965           * Set_Protocol at all; Ignore any error.
 966           */
 967 -	err = usbd_req_set_protocol(uaa->device, NULL,
 968 -	    uaa->info.bIfaceIndex, 1);
 969 +	if (!usb_test_quirk(uaa, UQ_MS_NO_SETPROTO))
 970 +		err = usbd_req_set_protocol(uaa->device, NULL,
 971 +		    uaa->info.bIfaceIndex, 1);
 972  
 973  	err = usbd_transfer_setup(uaa->device,
 974  	    &uaa->info.bIfaceIndex, sc->sc_xfer, ums_config,
 975 diff --git a/sys/dev/usb/quirk/usb_quirk.c b/sys/dev/usb/quirk/usb_quirk.c
 976 index 91d47935221f..d3075466dbb3 100644
 977 --- a/sys/dev/usb/quirk/usb_quirk.c
 978 +++ b/sys/dev/usb/quirk/usb_quirk.c
 979 @@ -654,6 +654,7 @@ static const char *usb_quirk_str[USB_QUIRK_MAX] = {
 980  	[UQ_UMS_IGNORE]		= "UQ_UMS_IGNORE",
 981  	[UQ_MS_BAD_CLASS]	= "UQ_MS_BAD_CLASS",
 982  	[UQ_MS_LEADING_BYTE]	= "UQ_MS_LEADING_BYTE",
 983 +	[UQ_MS_NO_SETPROTO]	= "UQ_MS_NO_SETPROTO",
 984  	[UQ_MS_REVZ]		= "UQ_MS_REVZ",
 985  	[UQ_MS_VENDOR_BTN]	= "UQ_MS_VENDOR_BTN",
 986  	[UQ_NO_STRINGS]		= "UQ_NO_STRINGS",
 987 diff --git a/sys/dev/usb/quirk/usb_quirk.h b/sys/dev/usb/quirk/usb_quirk.h
 988 index 8e8bfd152eb8..e5dd0c950785 100644
 989 --- a/sys/dev/usb/quirk/usb_quirk.h
 990 +++ b/sys/dev/usb/quirk/usb_quirk.h
 991 @@ -53,6 +53,7 @@ enum {
 992  	UQ_UMS_IGNORE,          /* device should be ignored by ums class */
 993  	UQ_MS_BAD_CLASS,	/* doesn't identify properly */
 994  	UQ_MS_LEADING_BYTE,	/* mouse sends an unknown leading byte */
 995 +	UQ_MS_NO_SETPROTO,	/* device should not receive SetProtocol requests */
 996  	UQ_MS_REVZ,		/* mouse has Z-axis reversed */
 997  	UQ_MS_VENDOR_BTN,	/* mouse has buttons in vendor usage page */
 998  	UQ_NO_STRINGS,		/* string descriptors are broken */
 999 diff --git a/sys/dev/vt/hw/fb/vt_fb.c b/sys/dev/vt/hw/fb/vt_fb.c
1000 index 96c54cfbe6ca..011aa1b3ebc4 100644
1001 --- a/sys/dev/vt/hw/fb/vt_fb.c
1002 +++ b/sys/dev/vt/hw/fb/vt_fb.c
1003 @@ -160,11 +160,22 @@ vt_fb_setpixel(struct vt_device *vd, int x, int y, term_color_t color)
1004  {
1005  	struct fb_info *info;
1006  	uint32_t c;
1007 -	u_int o;
1008 +	u_int o, row, col;
1009  
1010  	info = vd->vd_softc;
1011  	c = info->fb_cmap[color];
1012 -	o = info->fb_stride * y + x * FBTYPE_GET_BYTESPP(info);
1013 +
1014 +	/* Rotations */
1015 +	if (info->fb_flags & FB_FLAG_ROTATE_90)
1016 +		row = x, col = y;
1017 +	else
1018 +		row = y, col = x;
1019 +	if (info->fb_flags & FB_FLAG_ROTATE_180)
1020 +		row = (info->fb_height - 1) - row;
1021 +	if (!(info->fb_flags & FB_FLAG_ROTATE_90) !=
1022 +	    !(info->fb_flags & FB_FLAG_ROTATE_180))
1023 +		col = (info->fb_width - 1) - col;
1024 +	o = info->fb_stride * row + col * FBTYPE_GET_BYTESPP(info);
1025  
1026  	if (info->fb_flags & FB_FLAG_NOWRITE)
1027  		return;
1028 @@ -264,7 +275,7 @@ vt_fb_bitblt_bitmap(struct vt_device *vd, const struct vt_window *vw,
1029      unsigned int x, unsigned int y, term_color_t fg, term_color_t bg)
1030  {
1031  	struct fb_info *info;
1032 -	uint32_t fgc, bgc, cc, o;
1033 +	uint32_t fgc, bgc, cc, o, row, col;
1034  	int bpp, bpl, xi, yi;
1035  	int bit, byte;
1036  
1037 @@ -297,7 +308,18 @@ vt_fb_bitblt_bitmap(struct vt_device *vd, const struct vt_window *vw,
1038  			/* Skip pixel write, if mask bit not set. */
1039  			if (mask != NULL && (mask[byte] & bit) == 0)
1040  				continue;
1041 -			o = (y + yi) * info->fb_stride + (x + xi) * bpp;
1042 +
1043 +			/* Rotations */
1044 +			if (info->fb_flags & FB_FLAG_ROTATE_90)
1045 +				row = x + xi, col  = y + yi;
1046 +			else
1047 +				row = y + yi, col = x + xi;
1048 +			if (info->fb_flags & FB_FLAG_ROTATE_180)
1049 +				row = (info->fb_height - 1) - row;
1050 +			if (!(info->fb_flags & FB_FLAG_ROTATE_90) !=
1051 +			    !(info->fb_flags & FB_FLAG_ROTATE_180))
1052 +				col = (info->fb_width - 1) - col;
1053 +			o = row * info->fb_stride + col * bpp;
1054  			o += vd->vd_transpose;
1055  			cc = pattern[byte] & bit ? fgc : bgc;
1056  
1057 @@ -457,15 +479,64 @@ vt_fb_init(struct vt_device *vd)
1058  {
1059  	struct fb_info *info;
1060  	u_int margin;
1061 -	int bg, err;
1062 +	int angle = 0, bg, err;
1063  	term_color_t c;
1064 +	char *rotation, strbuf[4];
1065  
1066  	info = vd->vd_softc;
1067 -	vd->vd_height = MIN(VT_FB_MAX_HEIGHT, info->fb_height);
1068 -	margin = (info->fb_height - vd->vd_height) >> 1;
1069 -	vd->vd_transpose = margin * info->fb_stride;
1070 -	vd->vd_width = MIN(VT_FB_MAX_WIDTH, info->fb_width);
1071 -	margin = (info->fb_width - vd->vd_width) >> 1;
1072 +
1073 +	/*
1074 +	 * If we have been passed a rotation, and screen.rotate="AUTO", change
1075 +	 * screen.rotate to the autodetected rotation for use during the next
1076 +	 * reboot.
1077 +	 */
1078 +	if (info->fb_flags & FB_FLAG_ROTATE_NODEFAULT) {
1079 +		if ((rotation = kern_getenv("screen.rotate")) != NULL &&
1080 +		    strncasecmp(rotation, "auto", 5) == 0) {
1081 +			if (info->fb_flags & FB_FLAG_ROTATE_90)
1082 +				angle += 90;
1083 +			if (info->fb_flags & FB_FLAG_ROTATE_180)
1084 +				angle += 180;
1085 +			snprintf(strbuf, sizeof(strbuf), "%d", angle);
1086 +			kern_setenv("screen.rotate", strbuf);
1087 +		}
1088 +		freeenv(rotation);
1089 +	}
1090 +
1091 +	/* Default angle to rotate console clockwise, in 90 degree increments. */
1092 +	if (!(info->fb_flags & FB_FLAG_ROTATE_NODEFAULT)) {
1093 +		if ((TUNABLE_INT_FETCH("screen.autorotate", &angle) == 0))
1094 +			TUNABLE_INT_FETCH("screen.rotate", &angle);
1095 +		info->fb_flags &= ~FB_FLAG_ROTATE_MASK;
1096 +		switch (angle) {
1097 +		case 270:
1098 +			info->fb_flags |= FB_FLAG_ROTATE_270;
1099 +			break;
1100 +		case 180:
1101 +			info->fb_flags |= FB_FLAG_ROTATE_180;
1102 +			break;
1103 +		case 90:
1104 +			info->fb_flags |= FB_FLAG_ROTATE_90;
1105 +			break;
1106 +		default:
1107 +			info->fb_flags |= FB_FLAG_ROTATE_0;
1108 +			break;
1109 +		}
1110 +	}
1111 +
1112 +	if (info->fb_flags & FB_FLAG_ROTATE_90) {	/* +/-90 degrees rotation */
1113 +		vd->vd_height = MIN(VT_FB_MAX_HEIGHT, info->fb_width);
1114 +		vd->vd_width = MIN(VT_FB_MAX_WIDTH, info->fb_height);
1115 +		margin = (info->fb_height - vd->vd_width) >> 1;
1116 +		vd->vd_transpose = margin * info->fb_stride;
1117 +		margin = (info->fb_width - vd->vd_height) >> 1;
1118 +	} else {
1119 +		vd->vd_height = MIN(VT_FB_MAX_HEIGHT, info->fb_height);
1120 +		vd->vd_width = MIN(VT_FB_MAX_WIDTH, info->fb_width);
1121 +		margin = (info->fb_height - vd->vd_height) >> 1;
1122 +		vd->vd_transpose = margin * info->fb_stride;
1123 +		margin = (info->fb_width - vd->vd_width) >> 1;
1124 +	}
1125  	vd->vd_transpose += margin * (info->fb_bpp / NBBY);
1126  	vd->vd_video_dev = info->fb_video_dev;
1127  
1128 diff --git a/sys/kern/kern_ntptime.c b/sys/kern/kern_ntptime.c
1129 index a36016680a21..1d3e1dd2e65d 100644
1130 --- a/sys/kern/kern_ntptime.c
1131 +++ b/sys/kern/kern_ntptime.c
1132 @@ -1078,6 +1078,10 @@ static void
1133  start_periodic_resettodr(void *arg __unused)
1134  {
1135  
1136 +	EVENTHANDLER_REGISTER(power_resume, periodic_resettodr, NULL,
1137 +	    EVENTHANDLER_PRI_ANY);
1138 +	EVENTHANDLER_REGISTER(power_suspend_early, shutdown_resettodr, NULL,
1139 +	    EVENTHANDLER_PRI_FIRST);
1140  	EVENTHANDLER_REGISTER(shutdown_pre_sync, shutdown_resettodr, NULL,
1141  	    SHUTDOWN_PRI_FIRST);
1142  	callout_init(&resettodr_callout, 1);
1143 diff --git a/sys/sys/fbio.h b/sys/sys/fbio.h
1144 index 9123a2008b7a..d8e3e83d423b 100644
1145 --- a/sys/sys/fbio.h
1146 +++ b/sys/sys/fbio.h
1147 @@ -141,9 +141,15 @@ struct fb_info {
1148  	void		*fb_priv;	/* First argument for read/write. */
1149  	const char	*fb_name;
1150  	uint32_t	fb_flags;
1151 -#define	FB_FLAG_NOMMAP		1	/* mmap unsupported. */
1152 -#define	FB_FLAG_NOWRITE		2	/* disable writes for the time being */
1153 -#define	FB_FLAG_MEMATTR		4	/* override memattr for mmap */
1154 +#define	FB_FLAG_NOMMAP		    0x01	/* mmap unsupported. */
1155 +#define	FB_FLAG_NOWRITE		    0x02	/* disable writes for the time being */
1156 +#define	FB_FLAG_MEMATTR		    0x04	/* override memattr for mmap */
1157 +#define	FB_FLAG_ROTATE_0	    0x00	/* rotate fb 0 degrees clockwise */
1158 +#define	FB_FLAG_ROTATE_90	    0x08	/* rotate fb 90 degrees clockwise */
1159 +#define	FB_FLAG_ROTATE_180	    0x10	/* rotate fb 180 degrees clockwise */
1160 +#define	FB_FLAG_ROTATE_270	    (FB_FLAG_ROTATE_90 | FB_FLAG_ROTATE_180)
1161 +#define	FB_FLAG_ROTATE_MASK	    0x18
1162 +#define	FB_FLAG_ROTATE_NODEFAULT    0x20	/* do not load console defaults */
1163  	vm_memattr_t	fb_memattr;
1164  	int		fb_stride;
1165  	int		fb_bpp;		/* bits per pixel */

Attached Files

To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.
  • [get | view] (2024-04-24T03:39:05+0000, 5.8 KB) [[attachment:files_drm_510_kmod.shar]]
  • [get | view] (2024-04-24T01:23:12+0000, 19.2 KB) [[attachment:loader_rotate-13.3-RELEASE.diff]]
  • [get | view] (2024-04-24T01:23:51+0000, 0.6 KB) [[attachment:lua_commentparse-13.3-RELEASE.diff]]
  • [get | view] (2024-04-24T01:08:17+0000, 41.1 KB) [[attachment:multifix-13.3-RELEASE.diff]]
  • [get | view] (2024-04-24T01:24:12+0000, 0.6 KB) [[attachment:ntp-13.3-RELEASE.diff]]
  • [get | view] (2024-04-24T01:21:52+0000, 10.8 KB) [[attachment:thermal_management-13.3-RELEASE.diff]]
  • [get | view] (2024-04-24T01:23:36+0000, 2.9 KB) [[attachment:usb_hid_setprotocol-13.3-RELEASE.diff]]
  • [get | view] (2024-04-24T01:22:44+0000, 7.2 KB) [[attachment:vt_rotate-13.3-RELEASE.diff]]
 All files | Selected Files: delete move to page copy to page

You are not allowed to attach a file to this page.