Implement -P for boot loader. It's a bit easier to implement here than
in boot1, like is normally done. When a keyboard appears in the UEFI device tree, assume -D -h, just like on a BIOS boot. # It is unclear if an ACPI keyboard appearing in the tree means there's # a real keyboard or not. A USB keyboard doesn't seem to appear unless # it is really there. Differential Revision: https://reviews.freebsd.org/D5223
This commit is contained in:
parent
42e09be9c2
commit
cee34e3864
@ -66,6 +66,7 @@ EFI_GUID hoblist = HOB_LIST_TABLE_GUID;
|
||||
EFI_GUID memtype = MEMORY_TYPE_INFORMATION_TABLE_GUID;
|
||||
EFI_GUID debugimg = DEBUG_IMAGE_INFO_TABLE_GUID;
|
||||
EFI_GUID fdtdtb = FDT_TABLE_GUID;
|
||||
EFI_GUID inputid = SIMPLE_TEXT_INPUT_PROTOCOL;
|
||||
|
||||
#ifdef EFI_ZFS_BOOT
|
||||
static void efi_zfs_probe(void);
|
||||
@ -94,6 +95,88 @@ cp16to8(const CHAR16 *src, char *dst, size_t len)
|
||||
dst[i] = (char)src[i];
|
||||
}
|
||||
|
||||
static int
|
||||
has_keyboard(void)
|
||||
{
|
||||
EFI_STATUS status;
|
||||
EFI_DEVICE_PATH *path;
|
||||
EFI_HANDLE *hin, *hin_end, *walker;
|
||||
UINTN sz;
|
||||
int retval = 0;
|
||||
|
||||
/*
|
||||
* Find all the handles that support the SIMPLE_TEXT_INPUT_PROTOCOL and
|
||||
* do the typical dance to get the right sized buffer.
|
||||
*/
|
||||
sz = 0;
|
||||
hin = NULL;
|
||||
status = BS->LocateHandle(ByProtocol, &inputid, 0, &sz, 0);
|
||||
if (status == EFI_BUFFER_TOO_SMALL) {
|
||||
hin = (EFI_HANDLE *)malloc(sz);
|
||||
status = BS->LocateHandle(ByProtocol, &inputid, 0, &sz,
|
||||
hin);
|
||||
if (EFI_ERROR(status))
|
||||
free(hin);
|
||||
}
|
||||
if (EFI_ERROR(status))
|
||||
return retval;
|
||||
|
||||
/*
|
||||
* Look at each of the handles. If it supports the device path protocol,
|
||||
* use it to get the device path for this handle. Then see if that
|
||||
* device path matches either the USB device path for keyboards or the
|
||||
* legacy device path for keyboards.
|
||||
*/
|
||||
hin_end = &hin[sz / sizeof(*hin)];
|
||||
for (walker = hin; walker < hin_end; walker++) {
|
||||
status = BS->HandleProtocol(*walker, &devid, (VOID **)&path);
|
||||
if (EFI_ERROR(status))
|
||||
continue;
|
||||
|
||||
while (!IsDevicePathEnd(path)) {
|
||||
/*
|
||||
* Check for the ACPI keyboard node. All PNP3xx nodes
|
||||
* are keyboards of different flavors. Note: It is
|
||||
* unclear of there's always a keyboard node when
|
||||
* there's a keyboard controller, or if there's only one
|
||||
* when a keyboard is detected at boot.
|
||||
*/
|
||||
if (DevicePathType(path) == ACPI_DEVICE_PATH &&
|
||||
(DevicePathSubType(path) == ACPI_DP ||
|
||||
DevicePathSubType(path) == ACPI_EXTENDED_DP)) {
|
||||
ACPI_HID_DEVICE_PATH *acpi;
|
||||
|
||||
acpi = (ACPI_HID_DEVICE_PATH *)(void *)path;
|
||||
if ((EISA_ID_TO_NUM(acpi->HID) & 0xff00) == 0x300 &&
|
||||
(acpi->HID & 0xffff) == PNP_EISA_ID_CONST) {
|
||||
retval = 1;
|
||||
goto out;
|
||||
}
|
||||
/*
|
||||
* Check for USB keyboard node, if present. Unlike a
|
||||
* PS/2 keyboard, these definitely only appear when
|
||||
* connected to the system.
|
||||
*/
|
||||
} else if (DevicePathType(path) == MESSAGING_DEVICE_PATH &&
|
||||
DevicePathSubType(path) == MSG_USB_CLASS_DP) {
|
||||
USB_CLASS_DEVICE_PATH *usb;
|
||||
|
||||
usb = (USB_CLASS_DEVICE_PATH *)(void *)path;
|
||||
if (usb->DeviceClass == 3 && /* HID */
|
||||
usb->DeviceSubClass == 1 && /* Boot devices */
|
||||
usb->DeviceProtocol == 1) { /* Boot keyboards */
|
||||
retval = 1;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
path = NextDevicePathNode(path);
|
||||
}
|
||||
}
|
||||
out:
|
||||
free(hin);
|
||||
return retval;
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
main(int argc, CHAR16 *argv[])
|
||||
{
|
||||
@ -104,6 +187,7 @@ main(int argc, CHAR16 *argv[])
|
||||
struct devsw *dev;
|
||||
uint64_t pool_guid;
|
||||
UINTN k;
|
||||
int has_kbd;
|
||||
|
||||
archsw.arch_autoload = efi_autoload;
|
||||
archsw.arch_getdev = efi_getdev;
|
||||
@ -115,6 +199,8 @@ main(int argc, CHAR16 *argv[])
|
||||
archsw.arch_zfs_probe = efi_zfs_probe;
|
||||
#endif
|
||||
|
||||
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
|
||||
@ -150,15 +236,19 @@ main(int argc, CHAR16 *argv[])
|
||||
case 'D':
|
||||
howto |= RB_MULTIPLE;
|
||||
break;
|
||||
case 'm':
|
||||
howto |= RB_MUTE;
|
||||
break;
|
||||
case 'h':
|
||||
howto |= RB_SERIAL;
|
||||
break;
|
||||
case 'm':
|
||||
howto |= RB_MUTE;
|
||||
break;
|
||||
case 'p':
|
||||
howto |= RB_PAUSE;
|
||||
break;
|
||||
case 'P':
|
||||
if (!has_kbd)
|
||||
howto |= RB_SERIAL | RB_MULTIPLE;
|
||||
break;
|
||||
case 'r':
|
||||
howto |= RB_DFLTROOT;
|
||||
break;
|
||||
|
Loading…
Reference in New Issue
Block a user